home *** CD-ROM | disk | FTP | other *** search
- /*******************************************************************************\
-
- main module
-
- suntar 1.3.2, ©1991-92 Sauro & Gabriele Speranza
-
- This program is public domain, feel free to use it or part of it for anything
-
- \*******************************************************************************/
-
-
- #include "PB_sync.h"
- #include "antiglue.h"
-
- /*#include <EventMgr.h>
- #include <QuickDraw.h>
- #include <StdFilePkg.h>
- */
-
- #ifdef THINK_C_5
- #include <packages.h>
- #else
- #include <IntlPkg.h>
- #endif
- /*
-
- #include <DiskDvr.h>
- #include <DeviceMgr.h>
- */
-
- #include <string.h>
-
- #include "windows.h"
- #include "suntar.h"
-
- #define dp printf /* use it for debug, so it's easy to */
- /* find&delete all the extra print instructions */
-
-
- MenuHandle writeMenu,hackersMenu,tarPopupMenu,ntAPopupMenu;
-
- short err_code;
- short drive_number=0;
-
- options_type options;
- long last_selection=0;
- short again_command=0;
- sector_t sectors_on_floppy;
- OSType tar_creator,bar_creator,bar_type;
- static Boolean append_mode;
- Boolean in_Italia=false;
- Boolean ignore_errors=false;
- Boolean confirm_saves=false;
- Boolean expert_mode=false;
- Boolean non_convertire=false;
- Boolean disco_espulso; /* was my disk ejected ? */
- Boolean sto_lavorando=false; /* non usarlo se non per lo scopo attuale, dire al calcolo del
- tempo di sleep per WaitNextEvent di ritornare sempre 0, e sapere
- se devo abilitare il comando Pause
- -- consider it as a read only variable !*/
- static Boolean pausable=false;
- unsigned char file_aperto=0;
- static unsigned char check_ev_timing;
- #ifdef V_122
- Boolean smallFilesAreASCII;
- #endif
-
- short disable_binhex; /* bit 0: disable conversion
- bit 1: show info in extract
- bit 2: show info in list
- bit 3: save .info */
-
- short last_drive,preferred_drive;
- short back_prio;
-
- struct disk_info di;
-
- static Boolean preferences_changed=0; /* Apple (TN 188) discourages to call
- ChangedResource if it's not followed immediately by WriteResource,
- and I want to modify the file only once, and not to modify it if nothing
- changed */
- sector_t settori_passati;
-
- enum tipo_fase fase;
- short n_superdrives;
- sector_t file_current_s;
- short drive_type[max_drive];
- extern sector_t next_header_for_AIX;
- unsigned char window_title[]="\psuntar 1.3.2 - console";
- short default_flags =READONLY|CONSOLE|NOCLOSEBOX;
- extern short floppy_buffer_size;
- extern unsigned short hd_buffer_size;
-
-
- void handle_menus(long);
- void add_menu(void);
- short my_quit_handler(void);
- void EnableDisableItem(MenuHandle,short,Boolean);
- Boolean list_events(void);
- short dialogo_abort(void);
-
- static char diskWriteErrMsg[]="Disk write error %d\n";
- char DONE[]="Done\n",FINITO[]="Finito\n";
- char START_READ[]="Start reading\n";
-
-
-
- /***************** main ******************/
-
-
- /*
- suntar use an architecture which is unusual, at least in the Mac world:
- it has not a main event loop.
- When you have passed the first wave of horror and astonishment, I'll
- tell you how it works.
- The MainEvent routine calls GetNextEvent and serves the event, but:
- 1) it returns to the caller, it does not loop internally
- 2) it does not know how to serve all events, since it's part of the
- windows module and does not know anything about the tar/untar modules:
- you must enlarge its capabilities by providing an event filter and an
- "application specific menus handler", and maybe some "updaters" and
- "activaters" for windows (e.g. other filters)
- 3) some menu items (mainly, preferences) are handled immediately, but others only
- set the "last_selection" variable which the caller then examines and handles.
- That is, MainEvent is a relatively low-level routine, which is not allowed to
- take important decisions.
- So, suntar has several event loops, which call MainEvent, usually after installing
- different event filters. Furthermore, MainEvent is called periodically
- while suntar is working, with one further event filter which disables all the
- events which are not essential (almost all menu items are disabled during
- execution of commands). This architecture may easily emulate a typical Mac
- behaviour, but it's more flexible and powerful.
- Finally, MainEvent was broken into two parts, and sometimes one calls
- the two parts, doing its own event handling between the two calls, so reducing the
- need for a lot of filters.
- The result is that the program is organized in a UNIX-like fashion, the
- "master", the control center, is the main program, not the event loop. The most notable
- difference: rather than calling a "print menu screen & wait for an answer"
- suntar sets the "fase" variable (see later) and calls MainEvent in a loop
- until the global variable last_selection has a non-zero value.
- Other not obvious features in the basic architecture of suntar are:
- -) a "fase" (phase) global variable must always tell what suntar is currently
- doing, it's used to control the state of the menus (during work, many
- items are disabled) and sometimes some minor decisions (e.g. Expert list
- behaves slightly differently from List, but it's executed by the same
- function with the same parameters)
- -) background events are controlled from within the lowest level operations, hence
- high level functions cannot avoid to be paused or aborted (through
- a longjmp) nor avoid that the preferences settings be changed: they
- must ensure correct operation even in those situations.
-
- In other words: the body of suntar is written in a UNIX-like fashion: it
- believes to be the only one to take decisions, while Mac-like events (updates?
- activation of DAs? what are those things?) are left to another module which
- conceptually might be another task. But it's NOT another task, hence the UNIX-like
- part of suntar must explicitly activate the event module, by calling check_events
- (which obviously calls MainEvent).
- Furthermore, on UNIX (or VMS or MS-DOS) a menu selection looks like this:
-
- selection=my_menu(3,
- "-------------------------\n\
- 1 First command\n\
- 2 Second command\n\
- 3 Last choice\n\
- -------------------------\n\
- Your choice:");
-
- in suntar, one must have a menu resource and modify MaintainApplSpecificMenus
- in order to activate/deactivate them properly in the different phases of work
- and according to some status variables. Finally, one does this:
-
- fase= a phase in which that menu is enabled;
- last_selection=0; / * it should be still 0, but just in case... * /
- while(last_selection==0)
- MainEvent();
-
- Now last_selection contains the number of the requested command (note that some
- menu items are not known to the UNIX-like portion of suntar and are served by
- the other module without any report).
- The Mac-aware module is totally responsible for the text windows (windows,
- not window: it's a multiwindow system, but suntar exploits only one as the
- console). Since its was adapted from a text editor it may conceptually allow
- general-purpose text editing, but the UNIX-like portion exploits only its
- TTY-like capabilities.
- Anyway, choosing to emulate the most antiquate form of TTY (the one which
- printed on paper rather than on a CRT) has given to our module the possibility
- to scroll and resize the console window: Symantec in its ANSI library chose
- to give more power: modern video terminals have commands to clear the screen or
- position the cursor at any position, but in order to implement even only one
- such command they were obliged to fix the screen size to 25*80 characters
- (you can't position the cursor on the screen it there isn't a coordinate
- system on it), with no scroll, a very bad resize and a non-Mac feeling.
-
- So, a student who programmed mostly on UNIX (Sauro) and an engineer with UNIX
- and VMS experience (Gabriele) could write a Macintosh application without
- being obliged to change their habits. And anyway, this structure is flexible
- enough to allow us to write new fully-Mac routines (e.g. the options box) or
- to let the UNIX-like module handle some Mac-like events (easy, since there
- is no rigid rule about which module must handle which events: add a new event
- filter, and the responsibility for handling an event is moved to it).
-
- */
-
- void main()
- {
- short command;
- short files_to_be_opened;
- short last_file_opened=0;
-
- /* install the handlers for events which the window module doesn't know how
- to handle */
- my_handle_menus=handle_menus;
- my_add_menus=add_menu;
-
- /* initialize everything */
- /* l'ordine è importante perché a) ci sono delle dipendenze da variabili
- inizializzate da un'altra di esse, e b) determina dove sono caricate le
- risorse di codice e quindi la frammentazione della memoria */
- init_hqx_tab();
- InitConsole();
- prefs_da_risorsa();
- init_hd_buffering();
- init_buffering();
-
- /* new for suntar 1.3.2: if the user requested to open some files (e.g. by
- System 7's drag and drop) then open them */
- CountAppFiles(&command,&files_to_be_opened);
- if(files_to_be_opened!=0 && command==appPrint){ /* suntar can't print files ! */
- SysBeep(5);
- ExitToShell();
- }
-
- /* look at what disk drives and device driver are available */
- identifica_hardware();
-
- /* install the Quit handler */
- my_at_exit= my_quit_handler;
-
- /* main loop */
-
- /* debugging: open a second window so debugging prints don't mix with the
- normal outputs * /
- printf("inizio\n");
- pStrcpy(window_title,"\pDebug");
- new_window();
- / * */
-
-
- #if 0
- {barh_type barh;
- printf("offsets = %ld %ld %ld %ld\n",(long)(&tarh.linkflag-tarh.name),
- (long)(tarh.linkname-tarh.name),(long)(tarh.offset-tarh.name),(long)(sizeof(tarh)));
- printf("offsets = %ld %ld %ld %ld\n",(long)(&barh.linkflag-barh.mode),
- (long)(&barh.bar_magic[0]-barh.mode),(long)(barh.volume_num-barh.mode),(long)(sizeof(barh)));
- printf("offsets = %ld %ld %ld %ld\n",(long)((char*)&macbinh.finfo-&macbinh.nlen),
- (long)(macbinh.unused-&macbinh.nlen),(long)((char*)&macbinh.lastbyte17/*headlen[0]*/-&macbinh.nlen),
- (long)(sizeof(macbinh)));
- }
- #endif
-
-
- for(;;){
- fase=non_faccio_nulla;
- set_skip_all(0);
- if(last_file_opened==files_to_be_opened) close_all_open_WD();
- check_ev_timing=120;
- flush_buffers();
- enable_autoflush();
-
- last_selection=0;
- while(last_selection==0){
- if(last_file_opened!=files_to_be_opened && !file_aperto && !drive_number)
- last_selection=menuItemMess(fileID,fmOpen);
- else
- MainEvent();
- }
- fase=ricevuto_comando;
- settori_passati=0;
-
- /* sono possibili solo i menù Special e File, perché Preferences ed Edit sono gestiti
- subito e Write non è abilitato */
- if(hiword(last_selection)==hackID){
- if(loword(last_selection)==hmDriveList)
- DriveList(); /* it's the only command which needs no disk...*/
- else
- hacking(loword(last_selection));
- }
- /* non faccio else perché si può uscire dall'hacking anche con un comando
- del menù File, che va eseguito
- -- don't do 'else': I can exit from hacking with a File menu command which must be
- executed */
-
- command=loword(last_selection);
-
- if(hiword(last_selection)==fileID){
- again_command=0;
- last_selection=0;
- if(command==fmGetInfo){
- listonly=2;
- apri_archivio(aa_getinfo,0);
- }
- else if(command==fmOpen){
- listonly=0;
- if(last_file_opened!=files_to_be_opened){
- apri_archivio(aa_load,++last_file_opened);
- }
- else
- apri_archivio(aa_open,0);
- }
- else if(command==fmClose){
- if(file_aperto)
- chiudi_archivio();
- else
- diskEject();
- }
- else if(command ==fmCopy)
- copia_da_disco_a_file();
- else if(command==fmList){
- listonly=1;
- estrai_da_floppy();
- }
- else if(command==fmExtract){ /* extract, con de-macBinarizzazione e conversione LF->CR */
- listonly=0;
- estrai_da_floppy();
- }
- else if(command==fmSelect)
- select_and_extract();
- else if(command==fmWriteTar||command==fmWriteBar||command==fmAppend){
- bar_archive= command==fmWriteBar; /* non valido nel caso di append */
- append_mode= command==fmAppend;
- scrivi_su_floppy();
- }
- else if(command==fmFormat){
- disk_initialize();
- }
- }
- }
- }
-
- /**************** apri/chiudi archivio su file ***********/
-
- void apri_archivio(mode,indice) /* open a file archive */
- enum aa_mode mode;
- short indice;
- {
- long filesize;
- short nLF,forza_formato;
- FileParam fpb;
- Boolean not_ask_type,do_not_open;
- extern long file_date;
-
- if(setjmp(main_loop)<0) {
- return;
- }
-
- if(mode==aa_getinfo){
- SFTypeList myTypes;
- my_SF_Get(-1,myTypes);
- if(!reply.good) return;
- not_ask_type=true;
- }
- else if(mode==aa_open){
- if(! get_file_with_checkbox(¬_ask_type)) return;
- }
- else{ /* aa_load */
- AppFile fileInfo;
- GetAppFiles (indice,&fileInfo);
- ClrAppFiles (indice);
- reply.vRefNum=fileInfo.vRefNum;
- pStrcpy(reply.fName,fileInfo.fName);
- not_ask_type=true;
- printf("File %P\n",reply.fName);
- }
-
- fpb.ioFVersNum = 0;
- fpb.ioFDirIndex = 0;
- fpb.ioVRefNum=reply.vRefNum;
- fpb.ioNamePtr=reply.fName;
- if (PBGetFInfoSync(&fpb)) pbsyserr(&fpb);
- filesize=fpb.ioFlLgLen;
- sectors_on_floppy= (filesize+511)>>9;
-
- if(listonly){
- disable_autoflush(2);
- one_empty_line();
- printf("File %P ",reply.fName);
- printf("(data %ld+res %ld bytes)",fpb.ioFlLgLen,fpb.ioFlRLgLen);
- #if 0
- #define ALIAS_BIT 0x8000
- if(fpb.ioFlFndrInfo.fdFlags & ALIAS_BIT) printf(" alias"); /* currently
- that's useless, I'm using a non-custom standard file, which resolves aliases ! */
- #endif
- printf("\n");
- print_one_date(fpb.ioFlCrDat,in_Italia?"creato ":"created ");
- printf("\n");
- print_one_date(fpb.ioFlMdDat,in_Italia?"modificato ":"modified ");
- printf("\n");
- print_type_creator(fpb.ioFlFndrInfo.fdType,fpb.ioFlFndrInfo.fdCreator);
- printf("\n");
- enable_autoflush();
- }
- else
- one_empty_line();
-
- pStrcpy(tarh.name,reply.fName);
- my_p2cstr(tarh.name); /* these statements are useful only if the file is not */
- bar_archive=0; /* a tar/bar archive */
-
- /* tarh.mtime is examined later, nothing bad happens if it contains garbage
- but that's not good programming style */
- strcpy(tarh.mtime,"0");
- sect_n=0;
- end_of_file(); /* forse non necessario, ma prudente */
- copia_ultimo_header(&tarh,(sector_t)0); /* gli devo passare il numero del
- settore successivo all'header */
-
- if(filesize!=0 && !not_ask_type)
- forza_formato=dialogo_tipo_file();
- else
- forza_formato=0;
-
- do_not_open=true;
- if(!forza_formato && fpb.ioFlFndrInfo.fdType=='APPL')
- printf(in_Italia?"Applicazione\n":"Application\n");
- else if(!forza_formato && fpb.ioFlFndrInfo.fdType=='INIT')
- printf(in_Italia?"Estensione\n":"Extension\n");
- else if(!forza_formato && fpb.ioFlFndrInfo.fdType=='cdev')
- printf(in_Italia?"Pannello di controllo\n":"Control panel\n");
- else if(!forza_formato && (fpb.ioFlFndrInfo.fdType=='DFIL'||fpb.ioFlFndrInfo.fdType=='dfil'))
- printf(in_Italia?"Accessorio di scrivania\n":"Desk Accessory\n");
- else if(filesize==0)
- printf(in_Italia?"Data fork vuota\n":"Empty data fork\n");
- else
- do_not_open=false;
- if(do_not_open){
- if(!listonly) printf(in_Italia?"Questo tipo di file non può essere aperto da suntar\n":
- "This file type can\'t be opened by suntar\n");
- return;
- }
-
- /* Open the file only now, and don't open files with empty data fork:
- Disk Doubler extracts the resource fork of compressed files if I do that,
- but that's time consuming and useless */
-
- if(apri_file("rb",&inputFile))
- return;
-
- file_aperto=ff_tarbar;
- file_current_s=-1;
-
- if(forza_formato==ff_packit || forza_formato==0 && fpb.ioFlFndrInfo.fdType=='PIT '){
- /* don't examine the creator, there is at least one program (unpit)
- which creates PackIt files with another creator ('UPIT') */
- if(listonly)
- printf(in_Italia?"Archivio PackIt\n":"PackIt archive\n");
- else{
- select_directory();
- if(reply.good){
- file_date= -1;
- one_empty_line();
- printf(in_Italia?"Estrazione da archivio PackIt %s\n":
- "Unpacking PackIt archive %s\n", tarh.name);
- my_unpit();
- printf(in_Italia?FINITO:DONE);
- fine_lavoro();
- }
- chiudi_archivio();
- }
- }
- else if(!forza_formato&&is_hqx_name()>0 || forza_formato==ff_binhex){
- macbinh.cdate=fpb.ioFlCrDat;
- macbinh.mdate=fpb.ioFlMdDat;
- /* dopo di che non deve essere chiamato chkmacbin, che scarabocchia su macbinh...*/
-
- file_aperto=ff_binhex;
- fase=reading_disk;
-
- if(listonly)
- untar_file(filesize);
- else{
- select_directory();
- if(reply.good){
- one_empty_line();
- untar_file(filesize);
- printf(in_Italia?FINITO:DONE);
- fine_lavoro();
- }
- chiudi_archivio();
- }
- }
- else if((forza_formato==0 || forza_formato==ff_macbin||forza_formato==ff_c_macbin) &&
- chkmacbin (filesize,forza_formato)){
- file_aperto=ff_macbin;
- fase=reading_disk;
-
- copia_ultimo_header(&tarh,(sector_t)0);
- if(listonly)
- untar_file(filesize);
- else{
- select_directory(); /* per la verità, salvando un solo file potrei usare uno
- standard put, ma significherebbe fare modifiche più
- pesanti di quanto non voglia
- --having only one file to save I could use SFPutFile, but
- the existing routines don't expect more than a destination
- folder, and suntar was NOT meant as a file format converter,
- even if it can convert file formats, hence these commands
- are implemented according to the principle of "do that in
- the fewest statements with the fewest changes to existing
- routines"
- */
- if(reply.good){
- one_empty_line();
- untar_file(filesize);
- printf(in_Italia?FINITO:DONE);
- fine_lavoro();
- }
- chiudi_archivio();
- }
- }
- else if(forza_formato==ff_macbin||forza_formato==ff_c_macbin)
- error_message(in_Italia?"Formato non MacBinary\n":"Not a Macbinary file\n");
- else if(forza_formato==ff_ASCII||!forza_formato && isASCII(filesize,&nLF)>0 ){
- file_aperto=ff_ASCII;
- fase=reading_disk;
-
- if(listonly){
- printf(in_Italia ?"Contenente testo ASCII":"Containing ASCII text");
- if(nLF>0) printf(in_Italia?" con LF":" using LF");
- printf("\n");
- }
- else if(nLF==0){
- printf(in_Italia?"Testo ASCII in formato Macintosh, nessuna conversione\n":
- "ASCII text in Macintosh format, no conversion\n");
- chiudi_archivio();
- }
- else{
- if(reply.fName[0]>63-4) reply.fName[0]=63-4;
- pStrcat(reply.fName,"\p.out");
- my_SF_Put(in_Italia?"\pSalva testo Mac col nome:":"\pSave Mac text as:",reply.fName);
- if(reply.good){
- register short i;
- if(new_text_file(&info_file)==0){
- printf(in_Italia?"Converto %s in %P\n":"Converting %s to %P\n",tarh.name,reply.fName);
- info_file_open=1;
- while(filesize>0){
- if(filesize>=512L) i=512; else i= (short)filesize;
- filesize -= i;
- if(readblock(disk_buffer,i)!=0){
- disk_error_message();
- raise_error();
- }
-
- macize_ASCII(disk_buffer,512);
- if(mac_fwrite(disk_buffer,i,info_file)<0)
- write_error_message();
- }
- FSClose(info_file);
- info_file_open=0;
- }
- else
- error_message(in_Italia?"Errore nell\'apertura del file\n":"Error opening file\n");
- printf(in_Italia?FINITO:DONE);
- fine_lavoro();
- }
- chiudi_archivio();
- }
- }
- else{ /* the file is opened as a tar/bar archive */
- if(!listonly){
- one_empty_line();
- printf(in_Italia?"Apertura file %s\n":
- "Opening file %s\n", tarh.name);
- (void)identify_format();
- /*printf("\n");*/
- }
- else
- (void)identify_format();
- }
- if(listonly){
- chiudi_archivio();
- /*printf("\n");*/
- }
- }
-
- void chiudi_archivio()
- {
- file_aperto=0;
- FSClose(inputFile);
- }
-
- /***************** copia da disco a file ******************/
-
- void copia_da_disco_a_file() /* copy a disk archive to a file archive */
- /* trasferisce quello che vede in un file tar, senza estrarre i singoli files */
- {
- sector_t more_sectors;
- short inPlace;
- Boolean fine;
- long length;
- short outputFile;
- static unsigned char nome_ita[]="\parchivio", eng_name[]="\parchive";
-
- listonly=0; /* ad uso di floppy swap, le altre routines non le chiamo */
-
- if(setjmp(main_loop)<0) {
- FSClose(outputFile); /* non lo metto in raise_error... */
- return;
- }
-
- if(aspetta_inserzione(in_Italia?"\pInserisci il disco in formato UNIX":
- "\pInsert the disk in UNIX format",false) || di.is_not_initialized){
- FSClose(outputFile);
- return;
- }
-
-
- more_sectors=0;
-
- fase=reading_disk;
- bar_archive= identify_format()==bar_format;
-
- if(bar_archive){
- if( my_atoi(((barh_type*)disk_buffer)->volume_num,&floppy_n)) floppy_n = -1;
- if(floppy_n!=1) error_message(in_Italia?"Questo non è il primo disco\n":
- "That\'s not the first disk\n");
- }
-
- pStrcpy(disk_buffer,in_Italia?nome_ita:eng_name);
- pStrcat(disk_buffer,bar_archive?"\p.bar":"\p.tar");
-
- my_SF_Put(in_Italia?"\pSalva col nome:":"\pSave as:",disk_buffer);
- if(!reply.good) return;
-
- if(apri_file("wb",&outputFile)) return;
-
- one_empty_line();
- printf(in_Italia?"Inizio lettura\n":START_READ);
-
- if(!bar_archive)
- tar_check_floppy_swap(1); /* ci sono delle inizializzazioni */
- else{
- leggi_settore(0,&disk_buffer);
- if(check_error()) raise_error();
- if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
- beep_in_foreground();
- write_error_message();
- }
- bar_check_floppy_swap(1);
- }
-
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) raise_error();
-
- do{
- if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
- beep_in_foreground();
- write_error_message();
- }
- check_events();
- fine = more_sectors==0; /* fine del file corrente
- -- end of current file ? */
- if(fine){
- fine= check_all_zero(disk_buffer); /* fine dell'intero archivio
- -- end of the archive ? */
- if(!fine){
- unsigned char linkflag = get_linkflag(&length,true);
- last_offset=0;
- copia_ultimo_header(disk_buffer,sect_n+1); /* gli devo passare il numero del
- settore successivo all'header, da qui il +1 */
- if(length<0)
- fine=true;
- else{
- print_info(bar_archive?((barh_type*)disk_buffer)->name:disk_buffer,length);
- more_sectors=(length+511)/512;
- }
- }
- }
- else
- more_sectors--;
-
- if(!fine){
- sect_n++;
- if(bar_archive)
- bar_check_floppy_swap(more_sectors==0?-1:0);
- else
- tar_check_floppy_swap(more_sectors==0?-1:0);
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) raise_error();
- }
- }
- while(!fine);
-
- one_empty_line();
- printf(in_Italia ? "Lettura completata\n" : "Read completed\n");
- diskEject();
- FSClose(outputFile);
- fine_lavoro();
- }
-
- /***************** estrai da floppy ******************/
-
- void estrai_da_floppy() /* extract or list */
- {
- enum formats fmt;
-
- if(setjmp(main_loop)<0) {
- return;
- }
-
- if(!listonly){
- select_directory();
- if(!reply.good) return;
- }
-
- if(aspetta_inserzione(in_Italia?"\pInserisci il disco in formato UNIX":
- "\pInsert the disk in UNIX format",false) || di.is_not_initialized) return;
- one_empty_line();
- printf(in_Italia?"Inizio lettura\n":START_READ);
-
- disco_espulso=!listonly; /* per un extract non mi interessa impedire di espellere... */
- fase=reading_disk;
-
- fmt=identify_format();
- if(fmt==tar_format)
- my_untar();
- else if(fmt==bar_format)
- my_unbar();
-
- if(disco_espulso) diskEject();
- fine_lavoro();
- }
-
-
- /************ scrivi su floppy ******************/
-
-
- Boolean ins_checkbox_status;
-
- void set_exam_checkbox(WindowRecord *);
- static void set_exam_checkbox(w)
- WindowRecord *w;
- {
- short kind;
- Handle h;
- Rect r;
- extern Boolean sm_checkbox_status;
-
- sm_checkbox_status=ins_checkbox_status;
- GetDItem(w,4,&kind,&h,&r);
- SetCtlValue((ControlHandle)h,sm_checkbox_status);
- }
-
- void scrivi_su_floppy() /* handling of the Write menu */
- {
- Boolean ok_to_proceed;
- extern Boolean sm_checkbox_status;
-
- if(setjmp(main_loop)<0) {
- return;
- }
-
- ok_to_proceed=false;
-
- ins_checkbox_status=false;
-
- do{
- sm_checkbox_status=false; /* if the disk was in, nobody else clears it */
- if(aspetta_inserzione(in_Italia?"\pInserisci il disco su cui scrivere":
- "\pInsert the disk to be written",!append_mode)) return;
- ins_checkbox_status=sm_checkbox_status;
-
- if(is_wrprot() && (di.is_not_initialized||!ins_checkbox_status) ){
- printf_protetto();
- SysBeep(5);
- return;
- }
-
- if(di.is_not_initialized){
- disk_format(false);
- if(drive_number==0 && append_mode) return;
- }
- else{
- if(ins_checkbox_status){
- esamina_disco();
- if(drive_number==0)
- ;
- else if(is_wrprot()){
- printf_protetto();
- return;
- }
- else
- ok_to_proceed= warning_400_800()!=1;
- }
- else
- ok_to_proceed= warning_400_800()!=1;
- }
- }
- while(!ok_to_proceed);
-
-
- leggi_settore(0,&disk_buffer); /* serve come controllo di errore, e poi non so,
- potrebbe essere utile per la faccenda del TagBuffer */
- if(check_error()) return;
-
- fase=reading_disk;
-
- reset_sector_count();
- one_empty_line();
- if(append_mode){
- cerca_fine();
- }
- else
- printf(in_Italia?"Nuovo archivio %car\n":"New %car archive\n",bar_archive?'b':'t');
-
- for(;;){
- unsigned char itemname[32];
- fase=in_writing;
- print_ready();
- settori_passati=0;
- EnableItem(writeMenu, 0);
- GetIndString (itemname,128,bar_archive?2:1);
- SetItem (writeMenu,wmWriteTar,itemname);
- EnableDisableItem(writeMenu,wmSetLabel,bar_archive);
-
- DrawMenuBar();
- close_all_open_WD();
- check_ev_timing=120;
- flush_buffers();
- enable_autoflush();
- last_selection=0;
- while(last_selection==0){
- if(!bar_archive) EnableDisableItem(writeMenu,wmSetLabel,tar_version==tar_GNU);
- MainEvent();
- }
- DisableItem(writeMenu, 0);
- DrawMenuBar();
-
- if(last_selection==menuItemMess(fileID,fmAbort) ||
- last_selection==menuItemMess(writeID,wmEndWrite) ||
- last_selection==menuItemMess(fileID,fmEject) ){
- if(last_selection!=menuItemMess(writeID,wmEndWrite)) diskEject();
- return;
- }
- else if(hiword(last_selection)==writeID){
- my_tar(loword(last_selection));
- fine_lavoro();
- }
- /* non ci sono altri menù attivi: in principio pensavo di lasciare il List
- (senza espellere!) ma non serve, man mano che scrivo files sulla console
- vengono scritti i nomi ! */
- }
- }
-
-
- void disk_initialize()
- {
- short inPlace;
- short i;
-
- fase=initializing;
-
- i=aspetta_inserzione(in_Italia ? "\pInserisci il disco da inizializzare":
- "\pInsert the disk to be initialized",false);
-
- i=testa_stato(&inPlace,0);
- if(i!=0 || !inPlace){
- diskEject();
- return;
- }
- if(is_wrprot()){
- printf_protetto();
- SysBeep(5);
- return;
- }
- if(warning_first_write(1)<0){
- diskEject();
- return;
- }
-
- disk_format(crea_mac_dir);
- if(drive_number){
- if(testa_stato(&inPlace,1)){
- diskEject();
- }
- }
- }
-
-
- /*************************************************/
-
- enum formats identify_format()
- /* asks to the device driver about the current disk, than examines the
- first sectors to see whether it's a tar or bar archive */
- {
- short i;
- sector_t j;
- #define SUPERDRIVE 4
-
- leggi_settore(0,disk_buffer);
- if(err_code<0){
- SysBeep(5);
- if(file_aperto){
- if(err_code==eofErr)
- printf(in_Italia?"Data fork vuota\n":"Empty data fork\n");
- else
- printf("File access error %d\n",err_code);
- }
- else if( drive_number<=4 && (i=drive_type[drive_number-1]&0x0F)!= SUPERDRIVE &&
- i!= SUPERDRIVE+1){
- printf(in_Italia ? "Disco non inizializzato o in formato 720/1440K\n" :
- "The disk is either uninitialized or 720/1440K\n");
- printf(in_Italia ? "Prova a inserirlo in un Superdrive" :
- "Try to insert it in a SuperDrive");
- if(n_superdrives==0)
- printf(in_Italia?" (su un Macintosh che ce l\'abbia)":
- " (on a Macintosh which has one)");
- printf("\n");
- }
- else if(di.is_not_initialized)
- printf(in_Italia ? "Disco non inizializzato\n" :
- "The disk is not initialized\n");
- else
- printf(in_Italia ? "Disco illeggibile\n" :
- "The disk is unreadable\n");
-
- return unreadable_disk;
- }
- previousFormat=tar_unknown;
-
- if( (fase==non_faccio_nulla || fase==in_writing) && di.os!=unknown_os)
- return unknown_format; /* durante un list o altro devo dire che il
- formato non è tar, ma per una unexpected_disk_insertion non
- c'è motivo di dare altri messaggi */
-
- if(di.os==mac_MFS||di.os==mac_HFS){
- /* disk_buffer still contains sector 0 */
- if(check_all_zero(disk_buffer) ){
- printf(in_Italia ? "Il disco non è in formato tar né bar\n" :
- "The disk format is neither tar nor bar\n");
- return unknown_format; /* A Mac disk
- with a null sector 0 should not be classified as an empty tar archive */
- }
- }
-
-
- i = tar_check_settore0(false);
- if(i>=0){
- if(previousFormat==tar_GNU)
- printf(in_Italia ? "Archivio in formato GNU tar\n" : "GNU tar archive\n");
- else
- printf(in_Italia ? "Archivio in formato tar\n" : "Tar archive\n");
- return tar_format;
- }
- i= bar_check_settore0(&j,false);
- if(i>=0){
- printf(in_Italia ? "Archivio in formato bar\n" : "Bar archive\n");
- return bar_format;
- }
- else{
- /* I controlli fatti da quelle routines sono rigorosi, basta che il checksum
- sia sbagliato... non vorrei solo per quello perdere ogni
- possibilità di esaminare il disco, la vecchia versione non è affatto rigida in
- proposito e neanche la nuova lo è per gli altri header, quindi faccio una
- discriminazione molto più approssimativa, tanto my_untar e my_unbar poi hanno
- dei controlli di errore */
-
- if(((barh_type*)disk_buffer)->bar_magic[0]== 'V' &&
- untar_dec_number(((barh_type*)disk_buffer)->volume_num,-1)!=-1){
- printf(in_Italia ? "Archivio in probabile formato bar\n" : "It looks like a bar archive\n");
- return bar_format;
- }
- else if(untar_number(((tarh_type*)disk_buffer)->size,-1)!=-1 &&
- untar_number(((tarh_type*)disk_buffer)->mtime,-1)!=-1){
- printf(in_Italia ? "Archivio in probabile formato tar\n" : "It looks like a tar archive\n");
- return tar_format;
- }
- else{
- if(fase!=hack_listing){
- SysBeep(5);
- disable_autoflush(2);
- if(file_aperto)
- printf(in_Italia ? "Il file" : "The file");
- else
- printf(in_Italia ? "Il disco" : "The disk");
- printf(in_Italia ? " non è in formato tar né bar" :
- " format is neither tar nor bar");
- if(!file_aperto&&tar_version==tar_AIX)
- printf(in_Italia?" (ma potrebbe essere un disco tar oltre il primo)":
- " (but it could be a tar disk following the first one)");
- printf("\n");
- enable_autoflush();
- }
- return unknown_format;
- }
- }
- }
-
-
- /***************** apri file *********************/
-
- short apri_file(modo,who) /* opens a file */
- char *modo;
- short *who;
- {
- short io;
-
- reply.fName[reply.fName[0]+1]='\0'; /* per il caso debba fare una printf...*/
- /* SetVol(NULL,reply.vRefNum); setta la directory: inutile */
-
- if(modo[0]=='r')
- io=FSOpen (reply.fName, reply.vRefNum, who);
- else if(modo[0]=='w')
- if(bar_archive)
- io=create_overwrite(bar_creator, bar_type, who);
- else
- io=create_overwrite(tar_creator, 'TARF', who);
- if(io!=noErr) {
- start_of_line();
- printf("failure opening %P (",reply.fName);
- if(io==opWrErr)
- printf("already open with write permission)\n");
- else
- printf("error %d)\n",io);
- return -1;
- }
- return 0;
- }
-
- OSErr new_text_file(outputFile) /* creates and opens a text file */
- short *outputFile;
- {
- short io;
- /* SetVol(NULL,reply.vRefNum); setta la directory: inutile e pericoloso */
-
- return create_overwrite(text_creator, 'TEXT',outputFile);
- }
-
- OSErr create_overwrite(c,t,who)
- OSType t,c;
- short *who;
- {
- OSErr io;
- io=Create(reply.fName, reply.vRefNum, c, t);
- if (io==noErr)
- io = FSOpen( reply.fName, reply.vRefNum, who );
- else if(io==dupFNErr){
- io = open_overwrite( reply.fName, reply.vRefNum, who );
- if(io==noErr){
- /* settare tipo e creatore: certo se il file esiste già dovrebbero
- essere gli stessi, ma meglio non fidarsi !
- -- type and creator must be modified
- */
- FileParam fpb;
- fpb.ioFVersNum = 0;
- fpb.ioFDirIndex = 0;
- fpb.ioVRefNum=reply.vRefNum;
- fpb.ioNamePtr= &reply.fName;
- if (PBGetFInfoSync(&fpb)==noErr){
- fpb.ioFlFndrInfo.fdType=t;
- fpb.ioFlFndrInfo.fdCreator=c;
- PBSetFInfoSync(&fpb);
- }
- }
- }
- return io;
- }
-
- short mac_fread(buff,nbytes,refNum)
- char *buff;
- short nbytes;
- short refNum;
- {
- long count = nbytes;
- if( (err_code=FSRead( refNum, &count, buff )) != noErr){
- if(err_code==eofErr){
- fillmem(&buff[count],0,512-(short)count);
- err_code=noErr;
- }
- else
- return -1;
- }
- return (short) count;
- }
-
- short mac_fwrite(buff,nbytes,refNum)
- char *buff;
- short nbytes;
- short refNum;
- {
- long count=nbytes;
- if( (err_code=FSWrite( refNum, &count, buff )) != noErr )
- return -1;
- return (short)count;
- }
-
- OSErr open_overwrite (fileName,vRefNum,refnum)
- /* apre la data fork del file, tagliando a zero bytes sia questa sia la
- resource fork
- -- opens the file data fork, truncating it and the resource fork to zero length
- */
- char *fileName;
- short vRefNum,*refnum;
- {
- short i = FSOpen(fileName,vRefNum, refnum);
- if(i==noErr){
- SetEOF(*refnum,0L);
- if( OpenRF (fileName,vRefNum,&i)==noErr){
- SetEOF(i,0L);
- FSClose(i);
- }
- i=noErr;
- }
- return i;
- }
-
- /**************** gestione eventi durante le operazioni ************/
-
- Boolean my_disk_is_in()
- {
- /* Called before exiting from a pause: checks whether the disk is where is
- expected, and if there are some obvious reasons to believe it's not the
- expected disk
- */
- static char s1[]="Disco cambiato !\n",
- s2[]="Changed disk !\n";
- {
- short inPlace;
- sector_t old_s=sectors_on_floppy;
- if (testa_stato(&inPlace,0) || !inPlace){
- printf(in_Italia?"Disco assente !\n" : "Missing disk !\n");
- flush_console();
- return false;
- }
- if(sectors_on_floppy!=old_s){
- sectors_on_floppy=old_s;
- printf(in_Italia?s1:s2);
- return false;
- }
- sectors_on_floppy=old_s;
- }
- {
- char buffer[512];
- short refnum;
- long space;
- enum os_type i;
- if( GetVInfo (drive_number, buffer, &refnum,&space) == nsvErr ) return true;
- /* no such volume: a non-Mac disk is not mounted hence...*/
- read_one_sector(2,buffer,drive_number);
- if(!err_code) i=riconosci_disco_mac(buffer);
- if(err_code || i!=mac_HFS&&i!=mac_MFS){
- UnmountVol (NULL,drive_number); /* however,
- in some cases (see comments to de_Mac_ize) it's mounted, at least if
- suntar is not in foreground */;
- return true;
- }
- printf(in_Italia?s1:s2);
- return false;
- }
- }
-
- void handle_pause()
- {
- enum tipo_fase old=fase;
- extern DialogPtr ListDialog;
- fase=paused;
- last_selection=0;
-
- if(my_windows[0].used) SetWTitle (&my_windows[0],in_Italia?"\p<< in pausa >>":"\p<< paused >>");
- {unsigned char itemname[32];
- GetIndString(itemname,129,4);
- SetItem (myMenus[fileM], fmPause, itemname);
- }
- flush_all();
-
- while(last_selection!=menuItemMess(fileID,fmPause) &&
- last_selection!=menuItemMess(fileID,fmAbort)){
- MainEvent(); /* be', non tutti
- i filtri ha senso chiamarli anche durante un pause, ma in realtà
- il pause non è attivo durante i filtri che "lavorano" come
- quello del disk insertion, restano solo quelli dei dialoghi che
- vanno chiamati perché gestiscono gli update
- --not all filters must continue to be called during a pause,
- but when pause is enabled some filters are not used, and the
- filters of semimodal and of the selection dialog must be called
- during pauses
- */
- if(last_selection==menuItemMess(fileID,fmPause) && drive_number && !my_disk_is_in() ){
- last_selection=0;
- }
- }
- if(last_selection==menuItemMess(fileID,fmPause)) last_selection=0;
- {unsigned char itemname[32];
- GetIndString(itemname,129,3);
- SetItem (myMenus[fileM], fmPause, itemname);
- }
- if(my_windows[0].used) SetWTitle (&my_windows[0],window_title);
- fase=old;
- }
-
- Boolean check_filter(EventRecord *); /* Think C 5 no more requires these
- silly prototypes before a function declaration, but only for static functions,
- and anyway suntar must still be compilable by Think C 4 */
- static Boolean check_filter(theEvent)
- /* event filter used while suntar is working: most events are ignored
- without being handled
- */
- EventRecord *theEvent;
- {
- switch(theEvent->what){
- case keyDown:
- if(theEvent->modifiers&cmdKey) break; /* se accetta la selezione menù deve
- accettare anche i command-tasto */
- /* else prosegui in sequenza
- -- else, since there is no break, continue with the following instruction */
- case autoKey:
- return false; /* the event must not be handled */
- break;
- case mouseDown:
- {
- WindowPtr whichWindow;
- short code=FindWindow( theEvent->where, &whichWindow );
- if(code!=inMenuBar && code!=inSysWindow && code!=inDrag &&
- code!=inGrow && whichWindow==FrontWindow())
- return false;
- else
- SetCursor(&arrow);
- }
- break;
- }
- return true;
- }
-
-
- void check_events()
- /* handle the events which are allowed while suntar is working, including
- the Pause command
- */
- {
- EventRecord myEvent;
-
- /* We've discovered that, in typical file extractions, check_events occupied up
- to 35% of processing time, even if no event was pending. Hence, events must be
- checked less often, but with care, otherwise suntar would lose its feel (it's
- good to be able to change preferences on the fly, and while it's working in
- background one does not like to notice a huge speed difference in the foreground
- application) */
-
- if(last_selection!=menuItemMess(fileID,fmPause)){ /* that's used by the following function */
- ++check_ev_timing;
- if( check_ev_timing< (gInBackground?back_prio:(fase!=reading_disk&&fase!=hack_listing||
- !listonly)?18:3) ){
- EventRecord myEvent;
- if((check_ev_timing&1) || !OSEventAvail(everyEvent,&myEvent))
- return;
- }
- check_ev_timing=0;
-
- sto_lavorando=pausable=true;
-
- /* what follows is the body of MainEvent, with an extra call in order to ignore
- all the events which are not urgent */
-
- if(get_event(&myEvent)){
- if(check_filter(&myEvent)){
- if(my_event_filter!=NULL) (*my_event_filter)(&myEvent);
- handle_event(&myEvent);
- }
- }
- sto_lavorando=pausable=false;
- }
- if(last_selection==menuItemMess(fileID,fmPause))
- handle_pause();
- accept_abort_command();
- }
-
- short check_error_and_events()
- {
- /* in theory it's:
- if(check_error()) return -1;
- check_events();
- return 0;
- in practice, it was extended to transform a "missing disk" error to a pause,
- so you (and we) won't lose your work for an unwanted eject (it happened to us
- for a 4Megabytes file, filling 3 disks, and we had to start again after
- half an hour of work in background). But the caller must read the sector again,
- hence a new return code of 1
- */
- if(err_code!=-65){
- if(check_error()) return -1;
- check_events();
- return 0;
- }
- else{
- beep_in_foreground();
- start_of_line();
- printf(in_Italia?"Disco assente, pausa forzata\n":"Missing disk, a pause was forced\n");
- last_selection=menuItemMess(fileID,fmPause);
- check_events();
- return 1;
- }
- }
-
- void accept_abort_command()
- {
- if(last_selection == menuItemMess(fileID,fmAbort)){
- if(fase==reading_disk&&!listonly||fase==writing_disk||fase==selected_reading||fase==paused){
- if(dialogo_abort()==2){
- last_selection=0;
- return;
- }
- }
- one_empty_line();
- error_message(in_Italia?"Comando abortito\n":"Command aborted\n");
- }
- }
-
- Boolean is_abort_command()
- /* external routines must not know how I receive the Abort command,
- but they must be able to know when they must abort themselves */
- {
- return last_selection == menuItemMess(fileID,fmAbort);
- }
-
- Boolean is_pause_command()
- {
- return last_selection == menuItemMess(fileID,fmPause);
- }
-
- /****************** gestione dialogo di inserzione *********/
-
- short filter_insert(EventRecord*);
- static short filter_insert(theEvent)
- EventRecord*theEvent;
- {
- if(theEvent->what==diskEvt){
- drive_number=loword(theEvent->message);
-
- if(drive_number<=last_drive){
- /*FlushVol (PNS,drive_number);*/
- UnmountVol (NULL,drive_number); /* smonta qualunque
- cosa si trovasse in precedenza in quel drive, e il disco stesso se è stato
- montato: inutile guardare al codice di errore ritornato
- -- the Finder often mounts even a tar archive, if it was formatted on a Mac
- (see de_Mac_ize in tar.c): anyway, it must not be mounted if I want to use
- it without being disturbed by the Finder; the returned error code may be
- ignored, I don't worry to call this only when it was mounted...
- */
- return -1;
- }
- }
- else if(drive_number) /* the user may call the about_box, but about_box does
- not delay the handling of disk insertions (as options_box does), hence it's
- possible that the disk insertion event was handled by unexpected_disk_insertion */
- return -1;
- return 0;
- }
-
- /************* aspetta inserzione **************/
-
- short aspetta_inserzione(message,examine_disk)
- /* if a file or disk is already open, return immediately; otherwise,
- present the disk insertion dialog and update all the status informations
- about the current disk
- returns
- -1 or a error code <0: some error occurred, or the user clicked on Cancel
- 0: disk correctly inserted
- */
- char*message;
- Boolean examine_disk;
- {
- static Point wPos={-1,-1};
- static char*titoli[]={"\pAnnulla","\pEsamina il disco"};
- short inPlace;
- short i;
-
- if(drive_number!=0){
- if(testa_stato(&inPlace,0)==0){
- if(inPlace){
- if(di.is_not_initialized)
- printf(in_Italia?"Disco non inizializzato\n":"This disk is not initialized\n");
- return 0;
- }
- }
- else
- drive_number=0;
- }
- else if(file_aperto){
- di.is_not_initialized=false;
- di.os=unknown_os;
- di.disk_code=noMacDskErr;
- return 0;
- }
-
- if(preferred_drive){
- /* if there only one disk drive, or only one is a SuperDrive, eject anything
- was currently in that drive, since it's the only place where the user may insert
- the requested disk. But don't do that if a disk insertion on that drive has just
- happened
- */
- EventRecord event;
-
- drive_number=preferred_drive;
-
- if ( !OSEventAvail(diskMask,&event) || drive_number!=loword(event.message)){
- /*FlushVol (PNS,drive_number);*/
- UnmountVol (NULL,drive_number); /* inutile guardare al codice di errore ritornato */
- diskEject();
- }
- }
-
- i=semimodalDialog(examine_disk?144:138,&wPos,filter_insert,&titoli,examine_disk?2:1,
- message,in_Italia?"\p\r\rin un disk drive":"\p\r\rin a floppy disk drive",NULL,
- teJustCenter,fase==ricevuto_comando||fase==initializing,
- examine_disk?set_exam_checkbox:NULL);
-
- if(i==-1){
- if(testa_stato(&inPlace,1)){
- if(fase==initializing) return 0;
- diskEject();
- return -1;
- }
- return 0; /* disco inserito OK */
- }
-
- return -1; /* i==1, there are no other possible cases */
- }
-
- /************************************/
-
- void esamina_disco() /* examine a disk */
- {
- /* save global variables which must not be altered, but are used by
- some routines which I must call now */
- enum tipo_fase oldfase=fase;
- unsigned char savePrevFormat=previousFormat;
- Boolean savebar_archive=bar_archive;
- char savebuffer[512];
- enum formats j;
- mcopy(savebuffer,disk_buffer,512);
-
- fase=reading_disk; /* otherwise abort could be disabled */
- listonly=1; /* don't use buffering */
- /* I'm in a very peculiar situation, I must do a rather complex operation,
- requiring a number of function calls, but this operation is launched from
- within a very low level of another high level operation (disk_buffer is
- full, etc.). Hence, I must pay a lot of attention, suntar contains a lot
- of global variables and most of them can't be altered in this moment.
- Furthermore, this operation could raise an error, but I can't allow
- that raise_error be called, since it resets a lot of global variables,
- closes open files...
- The only reasonable solution is not to use the standard way of doing a
- List, but recreating it by using low-level functions (low enough that I can
- carefully examine all their instructions, and the instructions of the
- functions called by them) so that I can be sure that raise_error is not
- called, and I may be sure that the list of altered global variables is
- accurate.
- I wanted that the Abort command were active during this List (aborting
- the List and not anything else), hence I must handle it before it causes
- a raise_error, and that requires not using check_events too.
- */
-
- j=identify_format(); /* it can't cause a call to raise_error */
- if(j==tar_format||j==bar_format){
- bar_archive= j==bar_format;
- list_conciso();
- one_empty_line();
- }
- else if (di.os==mac_MFS || di.os==mac_HFS){ /* Try to print some informations,
- but without mounting the disk */
- leggi_settore(2,disk_buffer);
- if(err_code==0){
- static char *tot_files[2]={"Total files=%ld ","Numero totale di files=%ld "};
- disable_autoflush(2);
- printf("Volume %P (%ld KB ",&disk_buffer[36],
- ((*(unsigned short*)&disk_buffer[34]) * (*(long*)&disk_buffer[20]) )>>10 );
- printf(in_Italia?"disponibili)\n":"free)\n");
- if(di.os==mac_HFS){
- printf(tot_files[in_Italia?1:0],
- (long) ( max(1L,*(long*)&disk_buffer[84]) -1) ); /* do NOT count the
- Desktop file, but if it does not exist do not declare -1 files */
- printf(in_Italia?"(di cui %u nella radice)":"(%u in root)",
- max(1,*(unsigned short*)&disk_buffer[12]) -1 );
- printf(in_Italia?" numero cartelle totali=%ld":" total folders=%ld ",*(long*)&disk_buffer[88]);
- }
- else
- printf(tot_files[in_Italia?1:0],
- (long) ( max(1,*(unsigned short*)&disk_buffer[12]) -1) );
- printf("\n");
- enable_autoflush();
- }
- }
- bar_archive=savebar_archive;
- previousFormat=savePrevFormat;
- mcopy(disk_buffer,savebuffer,512);
- fase=oldfase;
- }
-
- void list_conciso() /* used by the "examine a disk" button */
- {
- long length;
- sector_t s_n=0;
-
- disable_autoflush(1);
-
- printf(in_Italia?"Contenuto attuale del disco:\n":"Current content of this disk:\n");
- if(bar_archive){
- short f_n;
- length=untar_number( ((barh_type*)disk_buffer)->size,-1);
- f_n=untar_dec_number( ((barh_type*)disk_buffer)->volume_num,-1);
-
- if(length==-1 || f_n==-1){
- printf(in_Italia?"Testata non in formato bar !\n":
- "Error: not a bar header !\n");
- enable_autoflush();
- return;
- }
- s_n = (length+1023)>>9;
- printf(in_Italia?"Disco numero %d":"Disk number %d",f_n);
- print_if_string(in_Italia?" dell\'archivio %s":" of the archive %s",
- ((barh_type*)disk_buffer)->name,100);
- printf("\n");
- }
-
- while(s_n<sectors_on_floppy){
- register unsigned char linkflag;
-
- if(list_events()){
- last_selection=0;
- one_empty_line();
- printf(in_Italia?"List interrotto\n":"List aborted\n");
- enable_autoflush();
- return;
- }
- leggi_settore(s_n,disk_buffer);
- if(check_error()){
- if(err_code==-65) drive_number=0; /* missing disk... */
- enable_autoflush();
- return;
- }
-
- if(check_all_zero(disk_buffer)){
- if(s_n==0||(bar_archive||hasVheader)&&s_n==1)
- printf(in_Italia?"Disco vuoto\n":"No files on disk\n");
- else
- printf(in_Italia?"Fine archivio\n":"End of archive\n");
- enable_autoflush();
- return;
- }
- linkflag= get_linkflag(&length,-1);
- if(linkflag==0xFF){
- printf(in_Italia?"Testata non in formato %car !\n":
- "Error: not a %car header !\n",bar_archive ? 'b' : 't');
- enable_autoflush();
- return;
- }
- if(linkflag!='1'&&linkflag!='2'){
- if(linkflag=='M'){
- if(!bar_archive) printf(in_Italia?"Parte del file %s\n":
- "Part of file %s\n",((tarh_type*)disk_buffer)->name);
- }
- else if(linkflag=='V'){
- if(!bar_archive) printf(in_Italia?"Il nome del disco è %s\n":
- "The disk name is %s\n",((tarh_type*)disk_buffer)->name);
- }
- else
- print_info(bar_archive ? ((barh_type*)disk_buffer)->name :
- ((tarh_type*)disk_buffer)->name,length);
- }
- s_n += (length+1023)/512;
- }
- printf(in_Italia?"Continua su un altro disco\n":"Continuing on another disk\n");
- enable_autoflush();
- }
-
- static Boolean list_events()
- /* replaces check_events during list_conciso */
- {
- EventRecord myEvent;
-
- ++check_ev_timing;
- if( check_ev_timing<3) return false;
- check_ev_timing=0;
-
- sto_lavorando=true;
-
- if(get_event(&myEvent)){
- if(check_filter(&myEvent)){
- if(my_event_filter!=NULL) (*my_event_filter)(&myEvent);
- handle_event(&myEvent);
- }
- }
- sto_lavorando=false;
-
- return last_selection == menuItemMess(fileID,fmAbort);
- }
-
- /*************************************************/
-
- void check_foreground()
- {
- /* to be called before interacting with the user when I could be
- running in background: if I am, call the Notification Manager to alert
- the user and wait for him/her to bring this application to foreground
- */
-
- if(gInBackground){
- NMRec my_notif_rec;
-
- my_notif_rec.qType=8;
- my_notif_rec.nmMark=1;
- #ifndef THINK_C_5
- my_notif_rec.nmSIcon=GetResource ('SICN',128);
- #else
- /* with another version of header files, it's */
- my_notif_rec.nmIcon=GetResource ('SICN',128);
- #endif
- my_notif_rec.nmSound=(void*)-1;
- my_notif_rec.nmStr=NULL;
- my_notif_rec.nmResp=NULL;
- NMInstall(&my_notif_rec);
- while(gInBackground)
- MainEvent();
- NMRemove(&my_notif_rec);
- #ifndef THINK_C_5
- ReleaseResource(my_notif_rec.nmSIcon);
- #else
- ReleaseResource(my_notif_rec.nmIcon);
- #endif
- }
- settori_passati=0;
-
- }
-
- void beep_in_foreground()
- {
- if(gInBackground)
- check_foreground(); /* which does a beep */
- else
- SysBeep(5);
- }
-
-
- /***********************/
-
- void update_about_box(EventRecord*);
- static void update_about_box(theEvent)
- EventRecord *theEvent;
- {
- WindowPtr theWindow=(WindowPtr)theEvent->message;
- static Rect
- boundsR1={10,105,30,475},
- boundsR2={40,130,140,475},
- boundsR3={148,5,285,300},
- dstRect1={5,5,129,129},
- dstRect2={148,288,258,476};
- Handle h;
- GrafPtr savePort;
- char*p;
-
- GetPort( &savePort );
- SetPort(theWindow);
- BeginUpdate( theWindow );
-
- TextFont(3);
- TextSize(12);
- p="suntar 1.3.2";
-
- TextBox(p,(long)strlen(p),&boundsR1,teJustCenter);
- TextFont(4);
- TextSize(9);
-
- if(in_Italia) p=
- "Suntar è il mezzo più semplice ed economico di comunicare\r\
- dati tra un Macintosh (dotato di SuperDrive) e un sistema\r\
- UNIX (con un drive per floppy disk da 3,5 pollici):\r\
- legge e scrive dischetti in formato tar UNIX, convertendo\r\
- automaticamente i files di testo e i formati MacBinary e\r\
- BinHex 4.0, usati negli archivi di pubblico dominio per\r\
- immagazzinare files Macintosh in files UNIX.\r\
- Sotto System 7, puoi usare gli aiuti a fumetti.";
- else
- p=
- "Suntar is the simplest and cheapest way to communicate\r\
- data between a Macintosh (with a SuperDrive) and a UNIX\r\
- machine (with a 3.5 inch floppy disk drive): it reads\r\
- and writes disks in the UNIX tar format, automatically\r\
- converting plain text files and the MacBinary and\r\
- BinHex 4.0 formats, used in public domain archives to\r\
- store Macintosh files in UNIX files.\r\
- Under System 7, help balloons are available.";
-
- TextBox(p,(long)strlen(p),&boundsR2,teJustRight);
-
- if(in_Italia) p=
- "suntar è un programma freeware\r\
- © 1991-92 Sauro e Gabriele Speranza\r\
- Indirizzo: Sauro Speranza via Cappuccini 18\r\
- 40026 Imola (Bo)\r\
- E-mail: speranza@cirfid.unibo.it\r\
- oppure: speranza@cs.unibo.it\r\
- Porzioni del programma sono © Gail Zacharias,\r\
- Symantec, Apple Computer, Allan Weber.\r\
- Scritto in Think C (© 1989-91\r\
- Symantec Corporation)";
- else p=
- "suntar is a freeware program\r\
- © 1991-92 Sauro and Gabriele Speranza\r\
- Address: Sauro Speranza via Cappuccini 18\r\
- 40026 Imola Italy\r\
- E-mail: speranza@cirfid.unibo.it\r\
- or: speranza@cs.unibo.it\r\
- Portions of suntar are © Gail Zacharias,\r\
- Symantec, Apple Computer, Allan Weber.\r\
- Written in Think C (© 1989-91\r\
- Symantec Corporation)";
-
- TextBox(p,(long)strlen(p),&boundsR3,teJustLeft);
-
- h=GetResource ('PICT',128);
- HLock(h);
- DrawPicture (h, &dstRect1);
- ReleaseResource(h);
- h=GetResource ('PICT',129);
- HLock(h);
- DrawPicture (h, &dstRect2);
- ReleaseResource(h);
-
- EndUpdate( theWindow );
- SetPort (savePort);
-
- }
-
- void about_box()
- {
- static Rect
- winRect={0,0,265,480};
- WindowPtr theWindow;
- short stato=0;
- EventRecord myEvent;
- enum tipo_fase old_fase=fase;
-
- flush_all();
- PositionDialog(&winRect);
- theWindow=NewWindow( NULL, &winRect, PNS, 1, dBoxProc, (WindowPtr)-1L, 0, (long)-1);
- ((WindowPeek)theWindow)->refCon= -3;
-
- install_handlers(theWindow, update_about_box, NULL);
- while(stato!=2){
- sto_lavorando=false; /* cursor shape and delay for WaitNextEvent... */
- fase=paused; /* for unexpected_disk_insertion */
- if(get_event(&myEvent)){
- if(myEvent.what==diskEvt){
- short olddrive=drive_number;
- unexpected_disk_insertion(myEvent.message);
- if(olddrive!=drive_number) break;
- }
- else if(myEvent.what==mouseDown)
- stato=1;
- else if(stato==1&&myEvent.what==mouseUp)
- stato=2;
- /* all other events are ignored: that's anyway a progress upon the 1.1 version,
- which never called GetNextEvent during the about box (background tasks and
- even screen savers were disabled...) */
- }
- }
-
- remove_handlers(theWindow);
- DisposeWindow(theWindow);
- fase=old_fase;
- /*Riattiva();*/
- }
-
-
- /************* check all zero **********/
-
- Boolean check_all_zero(buffer)
- char *buffer;
- {
- register short i=512/sizeof(long);
- register long n_or=0;
- register long* p= (long*) &buffer[0];
-
- while(--i>=0 && (n_or|= *p++) ==0L)
- ;
- return n_or==0L;
- }
-
- /************************/
-
- void print_info(name,length)
- char *name;
- long length;
- {
- if(name[strlen(name)-1]=='/')
- printf("Directory %s\n",name);
- else
- printf("File %s (%ld bytes)\n",name,length);
- }
-
- /*****************************/
-
- void raise_error()
- {
- /* prima di riprendere, chiamo tutte le routine di "cleanup", che ovviamente
- se non c'è niente da chiudere ritornano senza fare niente
- -- in suntar, all high level routines must use a setjmp to handle
- recovering after an error. All permanent entities (variables, files, windows)
- which need to be closed or restored to the normal state must be associated to
- a clean-up routine (which does nothing if no clean-up is needed) and that
- routine must be called here (beware, there's also a raise_hqx_error, which
- aborts the extraction of the current file but not the command)
- */
- SetCursor(&waitCursor); /* closing files may flush the disk cache, and that
- may take several seconds (at least, it was so before suntar had
- its own caching) */
- deall_tree();
-
- if(drive_number && dirty_buffers()){
- short refnum;
- long space;
- if( GetVInfo (drive_number, disk_buffer, &refnum,&space) == nsvErr ){
- /* no such volume: a non-Mac disk is not mounted hence...*/
- flush_buffers();
- }
- else
- invalid_buffers();
- }
-
- my_event_filter=NULL;
- if(fase==writing_disk || last_selection!=menuItemMess(fileID,fmAbort)){
- check_and_eject();
- chiudi_archivio();
- }
- last_selection=0;
- sto_lavorando=pausable=false;
- close_input_files();
- close_or_del_out_file();
- close_info_file();
- enable_autoflush();
- close_semimodal();
- FlushEvents( everyEvent, 0 );
- longjmp(main_loop,-1);
- }
-
- void error_message(p)
- char *p;
- {
- start_of_line();
- printf(p);
- raise_error();
- }
-
-
- void error_message_1(p,n)
- char *p;
- int n;
- {
- start_of_line();
- printf(p,n);
- raise_error();
- }
-
- /************************/
- short check_error()
- {
- /* da chiamare esclusivamente dopo leggi_settore
- -- to be called after leggi_settore */
- if(err_code){
- /* e se invece riprovassi a leggere ? Non è che il disk driver ritenti già lui? */
- disk_error_message();
- if(!ignore_errors){
- OSErr olderr=err_code;
- diskEject();
- err_code=olderr;
- return -1;
- }
- }
- return 0;
- }
-
- void disk_error_message()
- {
- start_of_line();
- if(err_code==-39 || file_aperto && err_code==-81)
- printf(in_Italia?"Fine del file prematura\n":"Error: unexpected end of file\n");
- else if(err_code==-65)
- printf(in_Italia?"Errore: disco assente\n" : "Error: missing disk\n");
- else if(err_code<=-66 && err_code>=-71)
- printf(in_Italia?"Settore illeggibile (errore %d)\n":
- "Unreadable sector (error code %d)\n",err_code);
- else if(err_code<=-72 && err_code>=-73)
- printf(in_Italia?"Settore difettoso (errore %d)\n":
- "Defective sector (error code %d)\n",err_code);
- else
- printf(in_Italia?"Errore di lettura n° %d\n":"Disk read error %d\n",err_code);
- }
-
- void write_error_message()
- /* to be called when mac_fwrite fails */
- {
- if(err_code==dskFulErr)
- error_message(in_Italia?"Errore: disco pieno\n":"Error: disk full\n");
- else if(err_code==ioErr)
- error_message("I/O error during file write\n");
- else if(err_code==wrPermErr)
- error_message("Error: no write permission\n");
- else
- error_message_1("File write error %d\n",err_code);
- }
-
- /***********************************************************************/
-
- void hacking(command)
- short command;
- /* handles all the commands in the Special menu: mainly for historical reasons
- (suntar 1.0 was rather modal) I preferred to loop internally while commands are
- from this menu rather than returning to the main loop after executing
- the first command
- */
-
- {
- /* visto che i comandi del menù Special sono attivi se e solo se lo sono quelli
- del menù file avrebbe senso eseguire un solo comando e ritornare, preferisco
- ciclare anche qui dentro perché così è più facile gestire il comando Again */
-
-
- short inPlace;
- register short i;
- Boolean sect_n_valid;
- Boolean out_f_open=false;
- sector_t default_sect_n=0;
- short outputFile;
- static unsigned char messIta[]="\pInserisci il disco di prova",
- messIng[]="\pInsert the test disk",
- mess_wrprot[]="Write protected disk !\n";
-
- next_header_for_AIX=-1;
- again_command=0;
- if(setjmp(main_loop)<0){
- if(out_f_open) FSClose(outputFile);
- if(again_command!=hmList || !drive_number)
- return; /* il disco è stato espulso, non ha senso restare qui dentro;
- non è detto però, forse a volte non espello ! */
- command=0;
- }
-
- if(aspetta_inserzione(in_Italia?messIta:messIng,false))
- return;
-
- for(;;){
- if(command==0){
- fase=non_faccio_nulla;
- close_all_open_WD();
- check_ev_timing=120;
- flush_buffers();
- enable_autoflush();
- last_selection=0;
- while(last_selection==0){
- MainEvent();
- if(!expert_mode) return;
- }
- if(again_command==hmView && (loword(last_selection)==hmView ||
- loword(last_selection)==hmAgain) && default_sect_n<sectors_on_floppy-1)
- default_sect_n++; /* tipicamente io guardo
- il settore prima di farci sopra un clear o read, per cui voglio un
- autoincremento solo se il comando resta view
- -- I usually view a sector just before clearing or untar-ring, hence
- I want auto-increment only if the following command is another View */
- command=loword(last_selection);
- fase=ricevuto_comando;
- if(hiword(last_selection)==fileID)
- return; /* non tocca a me gestirlo */
- last_selection=0;
- if(sect_n_valid=(command==hmAgain)){
- command=again_command;
- if(command==hmList){
- diskEject(); /* non avrebbe senso farlo due
- volte sullo stesso disco, ma ha senso farlo su più dischi di fila
- -- Do it again used on Expert list means do it on another disk,
- hence the current disk must be ejected */
- if(aspetta_inserzione(in_Italia?messIta:messIng,false))
- return;
- }
- }
- again_command=0;
- }
- else
- sect_n_valid=false;
-
- switch(command){
- case hmList:
- {
- enum formats fmt;
- if(drive_number) /* solo su disco, non su file */
- again_command=hmList;
- if(next_header_for_AIX!=-1 && tar_version==tar_AIX)
- fase=hack_listing; /* so identify_format doesn not print
- its "unknown format" message */
- one_empty_line();
- fmt = identify_format(); /* che legge in disk_buffer il settore 0
- -- which leaves a copy of sector 0 in disk_buffer */
- if(next_header_for_AIX!=-1 && tar_version==tar_AIX && fmt==unknown_format){
- /* printf("sn=%ld\n",next_header_for_AIX); */
- if(next_header_for_AIX < sectors_on_floppy){
- leggi_settore(next_header_for_AIX,&tarh);
- if(check_all_zero(&tarh)){
- print_sector_n(next_header_for_AIX);
- printf("End of Archive (dangerous, can\'t check it\'s the right disk)\n");
- break; /*save the value of next_header_for_AIX */
- }
- else if(untar_number(tarh.size,-1) != -1 &&
- untar_checksum(&tarh,-1,false) != -2)
- fmt=tar_format;
- else{
- printf("Unknown format (maybe wrong disk)\n");
- break;
- }
- }
- else{
- printf("No file starts here (dangerous, can\'t check it\'s the right disk)\n");
- next_header_for_AIX-=sectors_on_floppy;
- break;
- }
- }
- else
- next_header_for_AIX=-1;
-
- fase=hack_listing;
- if(fmt==bar_format){
- short n;
- one_empty_line();
- printf(START_READ);
- if(my_atoi(((barh_type*)disk_buffer)->volume_num,&n)!=0)
- printf("No sequence number\n");
- else
- stampa_info_bar(n);
- listonly=1;
- my_unbar(); /* che in caso di fase==hack_listing si comporta diversamente
- dal solito per il cambio disco, e stampa più informazioni
- -- which, when fase==hack_listing, behaves differently
- than when called by a List command */
- }
- else if(fmt==tar_format){
- one_empty_line();
- printf(START_READ);
- listonly=1;
- my_untar();
- }
- next_header_for_AIX=-1;
- }
- check_foreground();
- break;
- case hmClear: /* clear sector */
- case hmOverwrite:
- one_empty_line();
- if(is_wrprot()){
- printf(mess_wrprot);
- }
- else{
- if(command==hmClear){
- printf("Clearing the sector will erase its previous content.\n");
- printf(
- "If it was an header, List, Extract and Append will see it as end of the archive\n");
- sect_n=default_sect_n;
- }
- else{
- printf("The previous content will be lost\nstart ");
- sect_n=0;
- }
- fase=reading_sect_n;
- if(read_sect_n(§_n)==noErr){
- if(command==hmClear){
- fillmem(disk_buffer, 0, 512);
- scrivi_settore(sect_n,disk_buffer);
- if(err_code) printf(diskWriteErrMsg,err_code);
- }
- else{
- overwrite_sectors();
- printf(DONE);
- check_foreground();
- }
- default_sect_n=sect_n;
- }
- }
- break;
- case hmView: /* view sector */
- fase=reading_sect_n;
- one_empty_line();
- if(sect_n_valid)
- printf("View sector %ld\n",(long)sect_n);
- else{
- sect_n=default_sect_n;
- sect_n_valid= read_sect_n(§_n)==0;
- }
- if(sect_n_valid){
- fillmem(disk_buffer, 0, 512);
- read_sectors(sect_n,&disk_buffer,1);
- if(err_code){
- beep_in_foreground();
- disk_error_message();
- }
- stampa_buffer(sect_n,disk_buffer);
- again_command=command;
- default_sect_n=sect_n;
- if(sect_n<sectors_on_floppy-1) sect_n++;
- }
- break;
- case hmSave:
- {sector_t sect_finale;
- my_SF_Put("\pSave as:","\psectors");
- if(!reply.good) break;
-
- i=new_text_file(&outputFile);
- if(i!=noErr) break;
- out_f_open=true;
- sect_n=default_sect_n;
- fase=reading_sect_n;
- one_empty_line();
- if((printf("start "),read_sect_n(§_n)==0) &&
- (sect_finale=sect_n,printf("end "),read_sect_n(§_finale)==0) ){
-
- fase=reading_disk;
- do{
- check_events();
- leggi_settore(sect_n,&disk_buffer);
- if(check_error()) raise_error();
- if(mac_fwrite(disk_buffer, 512, outputFile)<=0){
- beep_in_foreground();
- write_error_message();
- }
- sect_n++;
- }
- while(sect_n<=sect_finale);
- }
- FSClose(outputFile);
- printf(DONE);
- check_foreground();
- out_f_open=false;
- }
- break;
- case hmFind:
- {short err_n=0;
- long exp_check;
- Boolean stampato=false;
- one_empty_line();
- fase=reading_disk;
- listonly=0; /* full buffering... */
- for(sect_n=0;sect_n<sectors_on_floppy;sect_n++){
- check_events();
- leggi_settore(sect_n,&disk_buffer);
- if(err_code!=noErr){
- printf("sector %ld could not be read\n",(long)sect_n);
- if(++err_n>max(20,(short)(sect_n/8))){
- beep_in_foreground();
- error_message("Too many errors, search aborted\n");
- }
- }
- else if(untar_number(((struct tarh_type*)disk_buffer)->size,-1) != -1 &&
- untar_checksum(&disk_buffer,-1,false) == 0){
- disk_buffer[99]=0;
- disable_autoflush(2);
- printf("tar ");
- print_sector_n(sect_n);
- if(((struct tarh_type*)disk_buffer)->linkflag=='V')
- printf("Volume header: ");
- if(((struct tarh_type*)disk_buffer)->linkflag=='M')
- printf("Continuation: ");
- printf("%s\n",disk_buffer);
- enable_autoflush();
- stampato=true;
- }
- else if(sect_n!=0&&untar_number(((barh_type*)disk_buffer)->size,-1) !=-1 &&
- unbar_checksum(&disk_buffer,-1,&exp_check) == 0 ){
- ((barh_type*)disk_buffer)->name[99]=0;
- printf("bar ");
- print_sector_n(sect_n);
- printf(" %s\n",((barh_type*)disk_buffer)->name);
- stampato=true;
- }
- }
- if(!stampato) printf("No headers found\n");
- printf(DONE);
- check_foreground();
- }
- break;
- case hmUntar:
- case hmUnbar:
- fase=reading_sect_n;
- one_empty_line();
-
- if(sect_n_valid)
- printf("Un%car at sector %ld\n",((command==hmUntar)?'t':'b'),(long)sect_n);
- else{
- sect_n=default_sect_n;
- sect_n_valid= read_sect_n(§_n)==0; /* come sopra */
- }
- if(sect_n_valid){
- leggi_settore(sect_n,&disk_buffer);
- if(err_code)
- disk_error_message();
-
- else if(check_all_zero(disk_buffer))
- printf("Null header\n");
- else{
- select_directory();
- if(reply.good){
- listonly=0;
- bar_archive= command==hmUnbar;
- fase=hack_reading; /* per avvertire di non chiedere un disco
- specifico: forse il settore 0 è danneggiato
- o sovrascritto da un altro header bar
- -- essentially, it's used to remember that
- the floppy_n variable may be invalid,
- hence when asking next disk don't rely on it */
- if(bar_archive){
- unbar();
- }
- else
- untar();
- print_sector_n(sect_n);
- printf(DONE);
- check_foreground();
- }
- again_command=command;
- default_sect_n=sect_n;
- }
- }
- break;
- case hmMac_ize:
- if(is_wrprot()){
- printf(mess_wrprot);
- }
- else{
- i=warning_first_write(1);
- if(i>=0){
- ioParam pb;
- Str255 volName;
- if(i>0){
- ParamText(i==1?"\pNon-Mac disk":"\pEmpty Macintosh disk",
- "\p\rAny data in this disk will be lost. Continue ?",PNS,PNS);
- if( my_modal_dialog(139,NULL,2) == 2) break;
- }
- ParamText("\pVolume name :",PNS,PNS,PNS);
- my_edt_dialog(143,volName,27,"\pUntitled");
- printf("Creating directory...\n");
- fillmem(disk_buffer, 0xF6, 512);
- write_sectors(0,disk_buffer,1);
- if(err_code)
- check_wr_err();
- else{
- DIZero (drive_number,volName);
- pb.ioVRefNum=drive_number;
- drive_number=0;
- PBMountVol(&pb);
- printf(DONE);
- }
- invalid_buffers();
-
- return;
- }
- else{
- diskEject();
- return;
- }
- }
- break;
- case hmDriveList:
- DriveList();
- break;
- } /* fine switch */
- command=0;
- }
- }
-
- short read_sect_n(n)
- sector_t *n;
- {
- char buffer[32];
- short i;
- printf("sector number : ");
- /* gets(buffer); */
- my_itoa((long)*n,buffer);
- prompt(buffer,sizeof(buffer)-1);
-
- #if SECTOR_T_SIZE==4
- i=my_atol(&buffer[0],n);
- #else
- i=my_atoi(&buffer[0],n);
- #endif
- if(i==0 && (*n<0 || *n >= sectors_on_floppy) ){
- printf("Invalid sector number\n");
- return -3;
- }
- else if(i==-2)
- printf("Invalid digit\n");
- return i;
- }
-
- short my_atoi(buffer,n)
- register char*buffer;
- register short *n;
- {
- for(;*buffer==' ';buffer++)
- ;
- if(*buffer>='0'&&*buffer<='9'){
- *n=0;
- while(*buffer>='0'&&*buffer<='9')
- *n= *n * 10 + *buffer++ -'0';
- return 0;
- }
- return *buffer? -2 : -1;
- }
-
- short my_atol(buffer,n)
- register char*buffer;
- register long *n;
- {
- for(;*buffer==' ';buffer++)
- ;
- if(*buffer>='0'&&*buffer<='9'){
- *n=0;
- while(*buffer>='0'&&*buffer<='9')
- *n= *n * 10 + *buffer++ -'0';
- return 0;
- }
- return *buffer? -2 : -1;
- }
-
- short untar_dec_number(buffer,doerror)
- char*buffer;
- short doerror;
- {
- short i;
- if(my_atoi(buffer,&i)){
- if(doerror>=0)
- printf(in_Italia?"Testata non in formato bar !\n":
- "Error: not a bar header !\n");
- if(doerror>0)
- raise_error();
- else
- return -1;
- }
- return i;
- }
-
- void macize_ASCII(buf,len)
- register char *buf;
- register short len;
- {
- /* one day, it could convert also MS-DOS text, by removing any LF preceded by
- a CR; but then it should have a way to return a len different than the original
- value, and the static variable storing the last char of the previous call will
- need to be cleared at the end of the file: too much work, and MS-DOS files
- are not very common within UNIX tar archives...
- */
- if(len)
- do{
- if(*buf==LF) *buf=CR;
- buf++;
- }
- while(--len);
- }
-
- void overwrite_sectors()
- {
- SFTypeList myTypes;
- short charsRead;
- extern char FERRORita[],FERRORing[];
-
- my_SF_Get(-1,myTypes);
- if(!reply.good) return;
-
- if(apri_file("rb",&inf_refn))
- return;
- inf_is_open=true;
- fase=writing_disk;
-
- while( (charsRead = mac_fread(disk_buffer, 512, inf_refn)) >0 ){
- if(sect_n>=sectors_on_floppy){
- printf("End of disk reached\n");
- break;
- }
- scrivi_settore(sect_n,disk_buffer);
- check_wr_err();
- sect_n++;
- check_events();
- }
- if(charsRead<0) printf(in_Italia?FERRORita:FERRORing,err_code);
-
- FSClose(inf_refn);
- inf_is_open=false;
- }
-
-
- void print_sector_n(sector_n)
- sector_t sector_n;
- {
- /* well, I use a printf which does not accept a %4d descriptor... !!! */
- printf("[sector %s%ld] ",sector_n>=1000?"":sector_n>=100?" ":sector_n>=10?" ":" ",
- (long)sector_n);
- }
-
- void stampa_info_bar(n) /* print informations from a bar volume header */
- short n;
- {
- char buffer[16];
- register short i,j;
- printf("Disk number %d ", n);
- for(i=j=0;i<10;i+=2,j+=3){
- buffer[j]=((barh_type*)disk_buffer)->cdate[i];
- buffer[j+1]=((barh_type*)disk_buffer)->cdate[i+1];
- }
- buffer[2]=buffer[5]='/';
- buffer[8]=' ';
- buffer[11]=':';
- buffer[14]='\0';
- printf("created %s",buffer);
- print_if_string("; archive name is %s",&((barh_type*)disk_buffer)->name[0],100);
- printf("\n");
- }
-
-
- /*********************************************/
-
-
- short going_to_background()
- /* to write on a disk in background is very dangerous, since suntar
- uses very low level calls and can't realize that a disk was replaced
- by a Mac disk containing precious files. Hence, the user must be
- alerted, and since at the next GetNextEvent I'll lose the right to get
- CPU time, I can't use a standard alert
- */
- {
-
- flush_all(); /* if the next foreground application is not MultiFinder aware,
- a lot of time (even hours) may pass before I have another chance to do
- that */
- if(fase==writing_disk && sto_lavorando){
- static Rect winRect={0,0,80,300},
- boundsR1={15,0,80,300};
- WindowPtr theWindow;
- GrafPtr savePort;
- char *p;
- unsigned long time;
-
- PositionDialog(&winRect);
- theWindow=NewWindow( NULL, &winRect, PNS, 1, dBoxProc, (WindowPtr)-1L, 0, (long)-1);
- GetPort( &savePort );
- SetPort(theWindow);
- p= in_Italia ?
- "suntar continuerà a scrivere in background\rsu qualunque cosa si trovi nel drive\r\
- non espellere il disco ! ! !":
- "suntar will write in background\ron anything is in the disk drive\r\
- please don\'t eject this disk";
-
- TextBox(p,(long)strlen(p),&boundsR1,teJustCenter);
-
- /* while(!Button()) ;
- while( Button()) ;
- FlushEvents( mDownMask|mUpMask, 0 ); */
- time=Ticks+delay_back; /* 5 secondi (nella risorsa), ma un clic del mouse riduce l'attesa
- purché siano almeno 1.5 */
- while (time >Ticks)
- if(time-delay_back+90 < Ticks && Button()){
- /*FlushEvents( mDownMask, 0 );*/ /* inutile, in pratica, l'evento va al
- processo successivo...
- -- a mouse click aborts the delay loop: however, I can't
- tell the Finder that that mouse click was already served,
- since that event is anyway passed to the application
- which is going to foreground, I can't flush it
- */
- break;
- }
- SetPort (savePort);
- DisposeWindow(theWindow);
- return 1;
- }
- return 0;
- }
-
- void DriveList()
- {
- short i;
- disable_autoflush(2);
- one_empty_line();
- for(i=0;i<max_drive;i++){
- if(drive_type[i]){
- printf("Drive %d: ",i+1);
- switch(drive_type[i]&0xF){
- case 7:
- printf("Hard disk 20 ");
- break;
- case 2:
- printf("Single sided (GCR 400k) ");
- break;
- case 3:
- printf("Double sided (GCR 800k) ");
- break;
- case 4:
- printf("SuperDrive (GCR 800k-MFM 720/1440k) ");
- break;
- case 5:
- {Handle h=GetResource('STR ',200);
- if(h){
- HLock(h);
- printf("%P ",*h);
- HUnlock(h);
- break;
- }
- }
- /* else unknown type */
- default:
- printf("Unknown drive type ");
- }
- if(drive_type[i]>0){ /* that bit is set/cleared by suntar */
- printf((drive_type[i]&0x100) ?"external":"internal");
- if(drive_type[i]&0x200) printf("(SCSI)");
- printf((drive_type[i]&0x400) ?", fixed (suntar can\'t open it)":", removable");
- }
- printf("\n");
- }
- }
- printf("\n");
- enable_autoflush();
- }
-
- void fine_lavoro()
- {
- if(gInBackground)
- check_foreground();
- else if(settori_passati>min_to_beep)
- SysBeep(5);
- }
-
- void unexpected_disk_insertion(message)
- /* called when a disk is inserted and suntar does not expect a disk insertion:
- obviously, that disk could be a Mac disk to be passed to the Finder, but it
- could be a tar disk, or it could be in the disk drive where suntar believes
- there was still the disk it has opened and on which it was working
- */
- long message;
- {
- extern Point badmount_point;
- extern char *titoli[];
- extern Boolean finestra_sm_aperta;
- jmp_buf savebuf;
- short inPlace;
- Boolean andata_male;
-
- sector_t old_s=sectors_on_floppy;
- short old_drive_n=drive_number;
- struct disk_info old_di=di;
-
- mcopy(&savebuf,&main_loop,sizeof(jmp_buf));
-
- andata_male=false;
- drive_number=loword(message);
-
- if(setjmp(main_loop)<0) { /* at least identify_format may do a raise_error, and
- raise_error causes a bad crash if no currently running function has performed
- a setjmp, and I don't know what's the current situation */
- andata_male=true;
- }
- if(andata_male || testa_stato(&inPlace,0)){
- diskEject();
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- sectors_on_floppy=old_s;
- drive_number=old_drive_n;
- di=old_di;
- return;
- }
-
- if( (di.os==mac_HFS||di.os==mac_MFS) && (drive_number!=old_drive_n || !dirty_buffers()) ){
- /* il disco non mi riguarda, lo lascio passare
- -- that disk is of no interest to suntar; do what GetNextEvent would do,
- then what Apple suggests to do when receiving a disk insertion event */
- ParamBlockRec param;
- param.volumeParam.ioVRefNum=loword(message);
- if( (hiword(message)=PBMountVol (¶m)) != noErr ){
- DIBadMount(badmount_point, message);
- invalid_buffers();
- }
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- sectors_on_floppy=old_s;
- drive_number=old_drive_n;
- di=old_di;
- return;
- }
-
- if(fase==non_faccio_nulla && old_drive_n==loword(message)){
- old_drive_n=0; /* there is no reason to ask the disk back if I was
- not working on it, simply close the old one */
- invalid_buffers();
- }
-
- if( old_drive_n!=0 || file_aperto){
- if((fase==paused || fase==in_writing || fase==reading_sect_n || finestra_sm_aperta) &&
- loword(message)==old_drive_n){ /* il disco
- era dentro, probabilmente è stato estratto a tradimento e poi reinserito
- -- the tar disk was in that drive, probably it was ejected (without using
- suntar's eject) and inserted in back */
- if (sectors_on_floppy!=old_s ){
- if(dirty_buffers())
- diskEject();
- else{
- ParamBlockRec param;
- param.volumeParam.ioVRefNum=loword(message);
- if (di.os==unknown_os || (hiword(message)=PBMountVol (¶m)) != noErr)
- DIBadMount(badmount_point, message);
- }
- }
- else{
- short item;
-
- ParamText(in_Italia?"\pQuesto è il disco su cui stavo lavorando ?":
- "\pIs this the disk I was working on ?",PNS,PNS,PNS);
- item=my_modal_dialog(139,titoli,2);
- if(item==2){
- /*FlushVol (PNS,drive_number);*/
- UnmountVol(NULL,drive_number);
- diskEject();
- }
- }
- }
- else{
- /* non accetto altri dischi
- -- suntar has something open and since it can't open more than one thing it can't
- open that disk, do something which looks like the standard behaviour
- for non-Mac or non-initialized disks
- */
- if(dirty_buffers())
- diskEject();
- else if(di.os==msdos){ /* AccessPC or DOS Mounter could be installed... */
- ParamBlockRec param;
- param.volumeParam.ioVRefNum=loword(message);
- if( (hiword(message)=PBMountVol (¶m)) != noErr ){
- DIBadMount(badmount_point, message);
- }
- }
- else{
- diskEject();
- ParamText(in_Italia?"\pNon si possono aprire due archivi":
- "\pCannot open more than one archive",PNS,PNS,PNS);
- my_alert();
- }
- }
- sectors_on_floppy=old_s;
- di=old_di;
- drive_number=old_drive_n; /* diskEject lo azzera */
- }
-
- else{ /* open it ! */
- if(testa_stato(&inPlace,true)) /* must call it again, for the "verbose" parameter */
- diskEject();
- else{
- if(drive_number<=last_drive && fase!=initializing){
- /*FlushVol (PNS,drive_number);*/
- /*i=*/ UnmountVol (NULL,drive_number);
- }
- if(di.os==msdos){
- ParamBlockRec param;
- param.volumeParam.ioVRefNum=drive_number;
- if( (hiword(message)=PBMountVol (¶m)) != noErr ){
- diskEject();
- ParamText(in_Italia?
- "\pDisco MS-DOS, per usarlo scegli un comando \"Create…\"":
- "\pMS-DOS disk, to open it select a \"Create…\" command",PNS,PNS,PNS);
- my_alert();
- }
- drive_number=0;
- }
- else if(!di.is_not_initialized)
- (void)identify_format();
- }
- }
- mcopy(&main_loop,&savebuf,sizeof(jmp_buf));
- }
-
- /************** gestione menù ****************/
-
- static void EnableDisableItem(menu, item, flag)
- MenuHandle menu;
- short item;
- Boolean flag;
- {
- if(flag)
- EnableItem(menu, item);
- else
- DisableItem(menu, item);
- }
-
- void MaintainApplSpecificMenus()
- /* it's an idea borrowed from TEsample: rather than enabling and disabling
- items when the situation changes, be sure that some global variables always
- tell what the situation is and adjust all the menu items when receiving a
- keyDown event with the Command key or a MouseDown event in the menu bar.
- That's the most reasonable way to do things in a program which has an abort
- command and does not quit at the first error.
- */
- {
- extern Boolean finestra_sm_aperta;
- extern DialogPtr ListDialog;
-
- Boolean b;
- b= fase==non_faccio_nulla;
- if(b){
- EnableDisableItem(myMenus[fileM], fmGetInfo, !file_aperto&&drive_number==0);
- EnableDisableItem(myMenus[fileM], fmCopy, !file_aperto);
- EnableItem(myMenus[fileM], fmList);
- EnableItem(myMenus[fileM], fmExtract);
- EnableDisableItem(myMenus[fileM], fmWriteTar, !file_aperto);
- EnableDisableItem(myMenus[fileM], fmWriteBar, !file_aperto);
- EnableDisableItem(myMenus[fileM], fmAppend, !file_aperto);
- EnableDisableItem(myMenus[fileM], fmFormat, !file_aperto);
- EnableItem(myMenus[fileM], fmSelect);
- }
- else{
- DisableItem(myMenus[fileM], fmGetInfo);
- DisableItem(myMenus[fileM], fmCopy);
- DisableItem(myMenus[fileM], fmList);
- DisableItem(myMenus[fileM], fmExtract);
- DisableItem(myMenus[fileM], fmWriteTar);
- DisableItem(myMenus[fileM], fmWriteBar);
- DisableItem(myMenus[fileM], fmAppend);
- DisableItem(myMenus[fileM], fmFormat);
- EnableDisableItem(myMenus[fileM], fmSelect, ListDialog&&FrontWindow()!=ListDialog);
- }
- /* il Think C marker non accetta macro su due righe, e non voglio perdere i suoi servizi ! */
- #define abort_mask ( (1<<writing_disk) | (1<<reading_disk) | (1<<reading_sect_n) | (1<<hack_reading) | (1<<hack_listing) | (1<<paused) | (1<<in_writing) | (1<<selected_reading) )
-
- EnableDisableItem(myMenus[fileM], fmPause, pausable || fase==paused /* nel secondo
- caso, l'item è diventato resume */ || finestra_sm_aperta&&((abort_mask>>fase)&1));
- EnableDisableItem(myMenus[fileM], fmOpen, fase==non_faccio_nulla&&drive_number==0&&!file_aperto);
-
- #ifdef V_122
- EnableDisableItem(myMenus[fileM], fmEject, drive_number!=0 &&( fase==non_faccio_nulla || fase==in_writing
- /* || fase==paused || finestra_sm_aperta*/) ); /* sarebbe sensato averlo attivo
- anche allora, ma non passo dal main per gestirlo ! */
- EnableDisableItem(myMenus[fileM], fmClose, fase==non_faccio_nulla&&file_aperto);
- #else
- /* in the 1.3 version, they share the same item */
- {
- unsigned char itemname[32];
- short i=2;
- if(!file_aperto&&drive_number==0)
- DisableItem(myMenus[fileM], fmEject);
- else{
- if(file_aperto)
- i=1;
- EnableDisableItem(myMenus[fileM], fmClose, fase==non_faccio_nulla || fase==in_writing);
- }
- GetIndString (itemname,129,i);
- SetItem (myMenus[fileM],fmClose,itemname);
- }
- #endif
-
-
- /*EnableDisableItem(myMenus[fileM], fmAbort, fase==writing_disk ||fase==reading_disk ||
- fase==reading_sect_n || fase==hack_reading || fase==hack_listing || fase==paused) ||
- fase==in_writing || fase==selected_reading; */
- EnableDisableItem(myMenus[fileM], fmAbort, (abort_mask>>fase)&1 );
-
- if(expert_mode){
- if(b){
- EnableItem(hackersMenu, hmView);
- EnableDisableItem(hackersMenu, hmClear,!file_aperto);
- EnableDisableItem(hackersMenu, hmMac_ize,!file_aperto);
- EnableDisableItem(hackersMenu, hmOverwrite,!file_aperto);
- EnableItem(hackersMenu, hmSave);
- EnableItem(hackersMenu, hmFind);
- EnableItem(hackersMenu, hmUntar);
- EnableItem(hackersMenu, hmUnbar);
- EnableItem(hackersMenu, hmList);
- EnableItem(hackersMenu, hmDriveList);
- EnableDisableItem(hackersMenu, hmAgain, again_command!=0);
- }
- else{
- DisableItem(hackersMenu, hmView);
- DisableItem(hackersMenu, hmClear);
- DisableItem(hackersMenu, hmMac_ize);
- DisableItem(hackersMenu, hmOverwrite);
- DisableItem(hackersMenu, hmSave);
- DisableItem(hackersMenu, hmFind);
- DisableItem(hackersMenu, hmUntar);
- DisableItem(hackersMenu, hmUnbar);
- DisableItem(hackersMenu, hmList);
- DisableItem(hackersMenu, hmDriveList);
- DisableItem(hackersMenu, hmAgain);
- }
- }
- }
-
-
- void set_skip_all(n)
- short n;
- {
- /* il confirm saves ha tre stati:
- non selezionato (confirm_saves=0,saveskip_all=0)
- selezionato (confirm_saves=1,saveskip_all=0)
- posto in corsivo da una skip all o save all (confirm_saves=0,saveskip_all=1)
- questa routine gestisce i passaggi tra i tre stati:
-
- n= 0 -> se è in corsivo torna sel, se no resta immutato;
- n= 1 -> da sel commuta a posto in corsivo (e da non sel resta immutato !)
- n=-1 -> da chiamare quando seleziono l'entry del menù: se è in corsivo torna selezionato,
- se no inverte lo stato attuale
-
- -- the confirm saves menu item has three states:
- non-selected (confirm_saves=0,saveskip_all=0)
- selected (confirm_saves=1,saveskip_all=0)
- italicized by a skip all or save all (confirm_saves=0,saveskip_all=1)
- this routine handles all its status changes:
- n=0 => I'm in the main loop, if it's italicized then make it selected
- 1 => the save all or skip all was clicked (caution, the confirm saves could
- have been disabled after the window appeared, and the button may still
- be clicked)
- -1 => the confirm saves menu item was selected: if italicized return normal,
- otherwise invert its current state
-
- */
- static Boolean saveskip_all=false;
-
- if(!n || (n<0&&saveskip_all) ){
- if(saveskip_all){
- saveskip_all=false;
- SetItemStyle(myMenus[prefM],pmConfirm,0);
- confirm_saves=true;
- }
- }
- else if (n>0){
- if(confirm_saves||saveskip_all){ /* può capitare che non sia così se
- deseleziono durante il dialogo e poi clicco su un bottone...*/
- saveskip_all=true;
- SetItemStyle(myMenus[prefM],pmConfirm, 2); /* corsivo */
- confirm_saves=false;
- }
- }
- else{ /* n=-1, saveskip_all=0 */
- CheckItem(myMenus[prefM],pmConfirm,confirm_saves^=1);
- }
- }
-
- void load_OSType(short,OSType *);
- static void load_OSType(id,dest)
- short id;
- OSType *dest;
- {
- Handle h;
- if((h=GetResource ('STR ',id))==NULL)
- *dest='????';
- else{
- HLock(h);
- mcopy((char*)dest,(char*)*h+1,4);
- ReleaseResource(h);
- /* *dest = (((long)*(unsigned char*)(*h+1))<<24) +
- (((long)*(unsigned char*)(*h+2))<<16) +
- (((long)*(unsigned char*)(*h+3))<<8) +
- ((long)*(unsigned char*)(*h+4)); */
- }
- }
-
- long load_number(short,short);
- static long load_number(id,deflt)
- short id;
- short deflt;
- {
- Handle h;
- if((h=GetResource ('STR ',id))==NULL)
- return deflt;
- else{
- long temp;
- HLock(h);
- temp=pstrtoi(*h);
- ReleaseResource(h);
- return temp;
- }
- }
-
- void prefs_da_risorsa()
- /* read all the preference settings which depend on a resource, including
- the INTL 0 resorce which is in the System file and contains the code
- for the nation, and compute the centered locations for those dialogs which
- are difficultly moved after their creation
- */
- {
- Handle h;
- short i;
- static Rect bmr={0,0,96,300};
- static short SF_IDs[]={199,200,-3999,-4000,1043,400,399};
- extern long my_uid,my_gid;
- extern char *uname,*gname;
- extern Boolean gHasCustomPutFile,SB3_compatibility;
- extern char *printf_buf;
- #define verItSwiss 36
-
- load_OSType(129,&tar_creator);
- load_OSType(136,&bar_creator);
- load_OSType(137,&bar_type);
-
- max_hqx_header=load_number(134,10240);
-
- my_uid=load_number(130,0);
- my_gid=load_number(131,0);
- list_buf_size=load_number(142,128);
- printf_buf=NewPtr((Size)list_buf_size);
-
- uname=gname="";
- ResrvMem ((Size)64);
- h=GetResource ('STR ',132);
- if(h){
- HLock(h);
- uname=my_p2cstr(*h);
- }
- h=GetResource ('STR ',133);
- if(h){
- HLock(h);
- gname=my_p2cstr(*h);
- }
-
- if((h=GetResource ('STR ',135))!=NULL ){
- if(**h){
- char c= *(*h+1)&~0x20;
- if(c=='I')
- in_Italia=true;
- else if(c=='E')
- in_Italia=false;
- else
- h=NULL;
- }
- else
- h=NULL;
- }
-
- #ifdef THINK_C_5
- #define Intl0Vers intl0Vers
- #endif
- if(h==NULL){
- h=IUGetIntl (0);
- if(h!=NULL){
- in_Italia=(((Intl0Rec*)*h)->Intl0Vers>>8)==verItaly ||
- (((Intl0Rec*)*h)->Intl0Vers>>8)==verItSwiss;
- ReleaseResource(h);
- CheckItem(myMenus[prefM],pmEnglish,!in_Italia);
- }
- }
-
- h=GetResource ('STR ',141);
- if(h && **h && ((*h)[1] | 0x20)!='n') SB3_compatibility=true;
-
- floppy_buffer_size =load_number(138,18);
- hd_buffer_size = load_number(139,20)<<9;
- back_prio = load_number(140,4);
-
- load_options();
-
- /* compute the centered position for the the disk initialization dialog */
- PositionDialog(&bmr); /* finestra usata da DIBadMount, uso dimensioni fisse
- che però sono quelle della finestra personalizzata e dovrebbero coincidere
- con quelle di sistema */
- *(long*)&badmount_point=*(long*)&bmr;
- /* sotto il System 7 passare {0,0} allo standard file provoca un dialogo
- centrato, ma purtroppo col system 6 non è così... */
-
- /* and the positions for the standard file dialogs */
- for(i=0;i<sizeof(SF_IDs)/sizeof(short);i++){
- AlertTHndl alertHandle = (AlertTHndl)GetResource('DLOG',SF_IDs[i]);
- if(alertHandle){
- PositionDialog( &((**alertHandle).boundsRect));
- where[i]=*(Point*)&((**alertHandle).boundsRect);
- }
- else{
- static Point def_where={80,80};
- where[i]=def_where;
- }
- }
- }
-
- void load_options()
- {
- static OSType gif_default='QGif';
- Handle h;
- if((h=GetResource ('OPTs',128))==NULL){
- /* create the options resource if it doesn't exist: probably that will not
- be useful to the user, we'll make suntar 1.2 and 1.3 available with an OPTs
- resource (otherwise, a file which grows could make somebody think about
- viruses) but during the development of the program it was useful,
- each time we changed the format of the resource, deleting the old one
- one obtains the creation of the new one */
- h=NewHandle(sizeof(options));
- fillmem(&options,0,sizeof(options));
- text_creator='EDIT';
- gif_creator=gif_default;
- resolve_aliases=useSys7_SF=true;
- non_text_ASCII=1;
- smallFilesAreASCII=1;
- delay_back=300;
- min_to_beep=500;
- del_incompl=true;
- mcopy(*h,&options,sizeof(options));
- AddResource (h, 'OPTs',128,PNS);
- WriteResource(h);
- }
- else{
- Size s=GetHandleSize(h);
- if(s<sizeof(options)){ /* somebody is using the old format of the OPTs
- resource (that of 1.2), convert it to the new format:
- it's always wise to support old formats for
- anything */
- SetHandleSize (h,(Size)sizeof(options));
- fillmem(*h+(&options.opt_bytes[12]-(char*)&options),0,8);
- *(char*)(*h+(&options.opt_bytes[12]-(char*)&options)) = 1;
- mcopy(*h+((char*)&options.gif_cr-(char*)&options),&gif_default,4);
- *( *h+(&options.opt_bytes[0]-(char*)&options) ) <<= 1; /* it's no more a Boolean... */
- ChangedResource(h);
- WriteResource(h);
- }
- mcopy(&options,*h,sizeof(options));
- }
- ReleaseResource(h);
- }
-
- void save_options()
- {
- Handle h;
- h=GetResource ('OPTs',128);
- mcopy(*h,&options,sizeof(options));
- ChangedResource(h);
- WriteResource(h);
- ReleaseResource(h);
- }
-
- void add_expert_menu(void);
- static void add_expert_menu()
- {
- unsigned char itemname[48];
- GetIndString(itemname,130,1);
- AppendMenu(myMenus[prefM],itemname);
- GetIndString(itemname,130,2);
- AppendMenu(myMenus[prefM],itemname);
- InsertMenu(hackersMenu = GetMenu(hackID),0);
- }
-
-
- static void add_menu() /* create application specific menus */
- {
- short markChar;
-
- CheckItem(myMenus[prefM],pmAutowrap,false);
- CheckItem(myMenus[prefM],pmConfirm,false);
- GetItemMark (hqxM,bmDisable,&markChar);
- disable_binhex = markChar==checkMark;
- GetItemMark (hqxM,bmShowExtr,&markChar);
- if(markChar==checkMark) disable_binhex |=2;
- GetItemMark (hqxM,bmSaveInfo,&markChar);
- if(markChar==checkMark) disable_binhex |=8;
- GetItemMark (hqxM,bmShowList,&markChar);
- if(markChar==checkMark) disable_binhex |=4;
-
- #ifdef V_122
- GetItemMark (myMenus[prefM],pmSmallText,&markChar);
- smallFilesAreASCII= markChar==checkMark;
- #endif
- GetItemMark (myMenus[prefM],pmExpert,&markChar);
- expert_mode= markChar==checkMark;
- InsertMenu(writeMenu = GetMenu(writeID), 0);
- DisableItem(writeMenu, 0);
- if(expert_mode) add_expert_menu(); /* always un-checked... */
- tarPopupMenu = GetMenu(tarPopupID);
- ntAPopupMenu = GetMenu(ntAPopupID);
-
- }
-
- static void handle_menus(choice) /* handle application specific menus */
- long choice;
- {
- if(hiword(choice)==appleID)
- about_box();
- else if(hiword(choice)==prefID)
- switch(loword(choice)) {
- case pmOptions:
- flush_all();
- options_box();
- break;
- case pmEnglish:{
- short markChar;
- in_Italia^=1;
- GetItemMark (myMenus[prefM],pmEnglish,&markChar);
- CheckItem(myMenus[prefM],pmEnglish,!markChar);
- }
- break;
- case pmConfirm:
- set_skip_all(-1);
- break;
- #ifdef V_122
- case pmSmallText:
- CheckItem(myMenus[prefM],pmSmallText, smallFilesAreASCII^=1);
- preferences_changed=true;
- break;
- #endif
- case pmExpert:
- CheckItem(myMenus[prefM],pmExpert,expert_mode ^=1);
- if(expert_mode){
- add_expert_menu();
- }
- else{
- DelMenuItem (myMenus[prefM], pmNoConvers);
- DelMenuItem (myMenus[prefM], pmIgnore);
- DeleteMenu (hackID);
- ignore_errors=non_convertire=false;
- }
- DrawMenuBar();
- preferences_changed=true;
- break;
- case pmIgnore:
- CheckItem(myMenus[prefM],pmIgnore,ignore_errors^=1);
- break;
- case pmNoConvers:
- CheckItem(myMenus[prefM],pmNoConvers,non_convertire^=1);
- break;
- }
- else if(hiword(choice)==hqxID){
- preferences_changed=true;
- switch(loword(choice)){
- case bmDisable:
- CheckItem(hqxM,bmDisable,(disable_binhex^=1)&1);
- break;
- case bmShowExtr:
- CheckItem(hqxM,bmShowExtr,((disable_binhex^=2)&2)!=0);
- break;
- case bmSaveInfo:
- CheckItem(hqxM,bmSaveInfo,((disable_binhex^=8)&8)!=0);
- break;
- case bmShowList:
- CheckItem(hqxM,bmShowList,((disable_binhex^=4)&4)!=0);
- break;
- }
- }
- else{ /* fileID o writeID oppure hackID, tanto non sono mai abilitati insieme,
- e comunque non butto via l'informazione
- -- I don't serve the command, rather I remember that it was selected.
- That's a matter of program hierarchy: MainEvent is a slave, it's not the
- master, hence important operations are not executed under it, and
- this routine is called from it.
- */
-
- if(choice==menuItemMess(fileID,fmSelect)&&ListDialog&&
- ListDialog != FrontWindow() ){
- SelectWindow(ListDialog);
- }
- else
- last_selection= choice;
- }
- }
-
- static short dialogo_abort()
- {
- ParamText(in_Italia?"\pVuoi interrompere il comando in corso ?":
- "\pDo you want to abort the current command and quit ?",PNS,PNS,PNS);
- beep_in_foreground();
- return my_modal_dialog(139,titoli,2);
- }
-
-
- static short my_quit_handler()
- {
-
- if(((abort_mask>>fase)&1) && fase!=in_writing){ /* it's the condition used for the abort menu item */
- if(dialogo_abort()==2) return 0;
- }
-
- check_and_eject(); /* ejects the disk and, if writing, flushes and truncates... */
-
- if(!preferences_changed) return 1;
-
- /* save the preferences settings */
- if(expert_mode){
- DelMenuItem (myMenus[prefM], pmNoConvers);
- DelMenuItem (myMenus[prefM], pmIgnore);
- }
- (**myMenus[prefM]).menuProc=NULL; /* without it, horrible things happen */
- ChangedResource(myMenus[prefM]);
- WriteResource(myMenus[prefM]);
-
- (**hqxM).menuProc=NULL;
- ChangedResource(hqxM);
- WriteResource(hqxM);
-
- close_or_del_out_file(); /* ExitToShell closes all files, but obviously does not
- flush my internal buffer nor delete incomplete files if that
- option is checked */
-
- return 1;
- }
-
- /******************/
-
- void print_chars(p,n)
- char* p;
- short n;
- {
- if(!n) return;
- while(--n)
- put_char(*p++);
- printf("%c",*p); /* to flush the buffer and update the scrollbars */
- }
-
- void flush_all()
- {
- if(dirty_buffers()) flush_buffers();
- flush_console();
- }
-